Skip to content

Instantly share code, notes, and snippets.

@metawops
Last active July 5, 2016 13:01
Show Gist options
  • Save metawops/9cb00b95d018f96f8091df2516cddc24 to your computer and use it in GitHub Desktop.
Save metawops/9cb00b95d018f96f8091df2516cddc24 to your computer and use it in GitHub Desktop.
NumberSpirals.pyui
#----------------------------------------------------------
# Title : Number Spirals Explorer
# Author : Stefan Wolfrum (@metawops)
# Date : June 2016
# License: CC0
#----------------------------------------------------------
import ui
import math
import webbrowser
from sympy.ntheory import isprime, sieve
from platform import machine
#--- NumberSpiralView class
class numberSpiralView (ui.View):
def __init__(self):
# This will also be called without arguments when the view is loaded from a UI file.
# You don't have to call super. Note that this is called *before* the attributes
# defined in the UI file are set. Implement `did_load` to customize a view after
# it's been fully loaded from a UI file.
self.transform = ui.Transform.translation(self.center[0], self.center[1])
device = machine()
if device == 'iPad6,7': # iPad Pro 12.9"
self.maxSpacing = 72.0
elif (device == 'iPad6,4') or (device == 'iPad5,4'): # iPad Pro 9.7" or iPad Air 2 9.7"
self.maxSpacing = 51.0
elif device == 'iPad5,1': # iPad mini 4 7.9"
self.maxSpacing = 51.0
self.turns = 3.0 # initial number of turns of the spiral
self.spacing = self.maxSpacing / self.turns
self.maxTurns = 100.0
self.drawAxis = False
self.drawDots = True
self.drawNumbers = True
self.autoSpacing = True
self.hilitePrimes = False
self.drawSpiral = True
self.primesOnly = False
self.drawCurve = False
self.curveParamA = 1.0
self.curveParamB = 1.0
self.curveParamC = 41.0
self.maxA = self.maxB = self.maxC = 80.0
self.spiralPath = ui.Path()
self.axisPath = ui.Path()
self.dotSize = 4.0
self.numberOffsetX = 0.0
self.numberOffsetY = 9.0
self.primeDotColor = '#e00'
self.numbersColor = '#000'
self.curveColor = '#3af'
self.curveDotsColor = (0.0, 0.0, 1.0, 0.5)
self.spiralColor = '#999'
self.dotsColor = '#666'
self.backgroundColor = '#eee'
#self.numberFont = ('<system>', 12)
self.numberFont = ('HelveticaNeue-Light', 8)
def setup(self):
#print('setup()')
self.listOfPrimes = [i for i in sieve.primerange(2,10000)]
self.background_color = self.backgroundColor
def did_load(self):
# This will be called when a view has been fully loaded from a UI file.
self.setup()
def will_close(self):
# This will be called when a presented view is about to be dismissed.
# You might want to save data here.
pass
def draw(self):
# This will be called whenever the view's content needs to be drawn.
# You can use any of the ui module's drawing functions here to render
# content into the view's visible rectangle.
# Do not call this method directly, instead, if you need your view
# to redraw its content, call set_needs_display().
self.axisPath = ui.Path()
self.spiralPath = ui.Path()
(self.cx, self.cy) = self.bounds.center()
if (self.drawAxis):
ui.set_color('black')
# x-Axis:
self.axisPath.move_to(0, self.cy)
self.axisPath.line_to(self.bounds[2], self.cy)
# y-Axis:
self.axisPath.move_to(self.cx, 0)
self.axisPath.line_to(self.cx, self.bounds[3])
#self.axisPath.move_to(cx+self.spacing*2.0*math.pi, 0)
#self.axisPath.line_to(cx+self.spacing*2.0*math.pi, self.height)
self.axisPath.stroke()
if (self.drawSpiral):
ui.set_color(self.spiralColor)
t = 0.0
max_t = self.turns * 2.0*math.pi
t_step = 0.08 # t_step constant for now but should be dynamic!
posx = posy = 0
self.spiralPath.move_to(posx + self.cx, posy + self.cy)
while (t < max_t-t_step):
t = t + t_step
posx = self.spacing * t * math.cos(t)
posy = self.spacing * t * math.sin(t)
self.spiralPath.line_to(posx + self.cx, -posy + self.cy)
# finally make sure that the end of the path lies exactly on the x-Axis:
finalx = self.spacing * max_t * math.cos(max_t)
finaly = self.spacing * max_t * math.sin(max_t)
self.spiralPath.line_to(finalx + self.cx, finaly + self.cy)
self.spiralPath.stroke()
if (self.drawDots):
n = 0
max_n = self.turns * self.turns
while (n <= max_n):
(x, y) = coordsForNumber(n)
dotx = self.cx + (x * self.spacing * 2*math.pi)
doty = self.cy + (y * self.spacing * 2*math.pi)
dotPath = ui.Path()
if self.hilitePrimes:
if (n in self.listOfPrimes):
ui.set_color(self.primeDotColor)
circlePath = ui.Path.oval(dotx-self.dotSize, doty-self.dotSize, 2*self.dotSize, 2*self.dotSize)
circlePath.fill()
if self.drawNumbers:
ui.draw_string(str(n), (dotx+self.dotSize+self.numberOffsetX, doty-(self.dotSize+self.numberOffsetY), 0, 0), self.numberFont, self.numbersColor)
else:
if not self.primesOnly:
ui.set_color(self.dotsColor)
circlePath = ui.Path.oval(dotx-self.dotSize, doty-self.dotSize, 2*self.dotSize, 2*self.dotSize)
circlePath.fill()
if self.drawNumbers:
ui.draw_string(str(n), (dotx+self.dotSize+self.numberOffsetX, doty-(self.dotSize+self.numberOffsetY), 0, 0), self.numberFont, self.numbersColor)
else:
if not self.primesOnly:
ui.set_color(self.dotsColor)
#dotPath.add_arc(dotx, doty, self.dotSize, 0, 2*math.pi)
#dotPath.fill()
circlePath = ui.Path.oval(dotx-self.dotSize, doty-self.dotSize, 2*self.dotSize, 2*self.dotSize)
circlePath.fill()
if self.drawNumbers:
ui.draw_string(str(n), (dotx+self.dotSize+self.numberOffsetX, doty-(self.dotSize+self.numberOffsetY), 0, 0), self.numberFont, self.numbersColor)
n = n + 1
if self.drawCurve:
curvePath = ui.Path()
curvePath.line_width = 4.0
curveDotsPath = ui.Path()
primesCounter = 0
# first point (n=0) requires a move_to:
f_n = self.curveParamC # a*0*0 + b*0 + c
if (f_n in self.listOfPrimes):
primesCounter = primesCounter + 1
(x, y) = coordsForNumber(f_n)
dotx = self.cx + (x * self.spacing * 2*math.pi)
doty = self.cy + (y * self.spacing * 2*math.pi)
curvePath.move_to(dotx, doty)
t = 1
max_t = self.turns * self.turns
while (f_n < max_t):
f_n = self.curveParamA*t*t + self.curveParamB*t + self.curveParamC
if f_n < max_t:
if (f_n in self.listOfPrimes):
primesCounter = primesCounter + 1
(x, y) = coordsForNumber(f_n)
dotx = self.cx + (x * self.spacing * 2*math.pi)
doty = self.cy + (y * self.spacing * 2*math.pi)
ui.set_color(self.curveColor)
curvePath.line_to(dotx, doty)
#curvePath.stroke()
#curveDotsPath = ui.Path()
#ui.set_color(self.curveDotsColor)
#curveDotsPath.add_arc(dotx, doty, self.dotSize+1, 0, 2*math.pi)
#curveDotsPath.fill()
t = t + 1.0
curvePath.stroke()
# number of dots under curve
# number of primes under curve
ui.draw_string("Number of dots under curve: {:.0f}".format(t), (10, 10, 0, 0), ('Menlo-Regular', 10), self.dotsColor)
ui.draw_string("Number of primes under curve: {:.0f}".format(primesCounter) + " ({:.1f}%)".format(primesCounter*100/t), (10, 24, 0, 0), ('Menlo-Regular', 10), self.primeDotColor)
#self.superview['labelLongestPrimeStreak'].text = "{:.0f}".format(primesCounter)
def layout(self):
# This will be called when a view is resized. You should typically set the
# frames of the view's subviews here, if your layout requirements cannot
# be fulfilled with the standard auto-resizing (flex) attribute.
device = machine()
if self.width > self.height:
self.scrOrientation = 'landscape'
if device == 'iPad6,7': # iPad Pro 12.9"
self.maxSpacing = 72.0
elif (device == 'iPad6,4') or (device == 'iPad5,4'): # iPad Pro 9.7" oder iPad Air 2 9.7"
self.maxSpacing = 51.0
elif device == 'iPad5,1': # iPad mini 4 7.9"
self.maxSpacing = 51.0
else:
self.scrOrientation = 'portrait'
if device == 'iPad6,7': # iPad Pro 12.9"
self.maxSpacing = 72.0
elif (device == 'iPad6,4') or (device == 'iPad5,4'): # iPad Pro 9.7" oder iPad Air 2 9.7"
self.maxSpacing = 30.0
elif device == 'iPad5,1': # iPad mini 4 7.9"
self.maxSpacing = 51.0
self.spacing = (1.0/self.turns) * self.maxSpacing
self.set_needs_display()
def touch_began(self, touch):
# Called when a touch begins.
pass
def touch_moved(self, touch):
# Called when a touch moves.
pass
def touch_ended(self, touch):
# Called when a touch ends.
pass
def keyboard_frame_will_change(self, frame):
# Called when the on-screen keyboard appears/disappears
# Note: The frame is in screen coordinates.
pass
def keyboard_frame_did_change(self, frame):
# Called when the on-screen keyboard appears/disappears
# Note: The frame is in screen coordinates.
pass
# end of Class NumberSpiralView
#--- TextField delegate
class CurveParamTextFieldDelegate (object):
def textfield_should_begin_editing(self, textfield):
return True
def textfield_did_begin_editing(self, textfield):
pass
def textfield_did_end_editing(self, textfield):
sv = textfield.superview
spiralView = sv['spiralView']
if textfield.name == 'textfieldA':
val = int(textfield.text)
sv['sliderA'].value = val/spiralView.maxA
spiralView.curveParamA = val
spiralView.set_needs_display()
elif textfield.name == 'textfieldB':
val = int(textfield.text)
sv['sliderB'].value = val/spiralView.maxB
spiralView.curveParamB = val
spiralView.set_needs_display()
elif textfield.name == 'textfieldC':
val = int(textfield.text)
sv['sliderC'].value = val/spiralView.maxC
spiralView.curveParamC = val
spiralView.set_needs_display()
def textfield_should_return(self, textfield):
textfield.end_editing()
return True
def textfield_should_change(self, textfield, range, replacement):
return True
def textfield_did_change(self, textfield):
pass
#--- Utilities ----------------------------------------------
def coordsForNumber(n):
r = theta = math.sqrt(n)
x = r * math.cos(2*math.pi*theta)
y = -r * math.sin(2*math.pi*theta)
return (x, y)
#--- Slider change ---------------------------------------
def sliderAchanged(sender):
spiralView = v['spiralView']
spiralView.curveParamA = int(sender.value * spiralView.maxA)
v['textfieldA'].text = "{:.0f}".format(spiralView.curveParamA)
spiralView.set_needs_display()
def sliderBchanged(sender):
spiralView = v['spiralView']
spiralView.curveParamB = int(sender.value * spiralView.maxB)
v['textfieldB'].text = "{:.0f}".format(spiralView.curveParamB)
spiralView.set_needs_display()
def sliderCchanged(sender):
spiralView = v['spiralView']
spiralView.curveParamC = int(sender.value * spiralView.maxC)
v['textfieldC'].text = "{:.0f}".format(spiralView.curveParamC)
spiralView.set_needs_display()
def sliderSpacingChanged(sender):
spiralView = v['spiralView']
spiralView.spacing = sender.value * spiralView.maxSpacing
v['labelSpacing'].text = "{:.1f}".format(spiralView.spacing)
spiralView.set_needs_display()
def sliderTurnsChanged(sender):
spiralView = v['spiralView']
spiralView.turns = int(sender.value * spiralView.maxTurns)
if spiralView.turns == 0:
spiralView.turns = 1
v['labelTurns'].text = "{:.0f}".format(spiralView.turns)
if v['switchAutoSpacing'].value:
spiralView.spacing = (1.0/spiralView.turns) * spiralView.maxSpacing
v['labelSpacing'].text = "{:.1f}".format(spiralView.spacing)
spiralView.set_needs_display()
# Settings dialog sliders
def sliderSettingsDotSizeChanged(sender):
spiralView = v['spiralView']
spiralView.dotSize = int(sender.value * 9.0 + 1.0)
sender.superview['labelDotSize'].text = "{:.0f}".format(spiralView.dotSize)
spiralView.set_needs_display()
def sliderSettingsFontSizeChanged(sender):
spiralView = v['spiralView']
spiralView.numberFont = ('HelveticaNeue-Light', sender.value * 23.0 + 8.0)
# Achtung! offset auch anpassen, proportional ... wie?
sender.superview['labelFontSize'].text = "{:.0f}".format(spiralView.numberFont[1])
spiralView.set_needs_display()
#--- Switch change --------------------------------------
def switchAutoSpacingChanged(sender):
v['sliderSpacing'].hidden = sender.value
spiralView = v['spiralView']
if sender.value:
spiralView.spacing = (1.0/spiralView.turns) * spiralView.maxSpacing
else:
v['sliderSpacing'].value = spiralView.spacing/spiralView.maxSpacing
v['labelSpacing'].text = "{:.1f}".format(spiralView.spacing)
spiralView.set_needs_display()
def switchDrawAxisChanged(sender):
spiralView = v['spiralView']
spiralView.drawAxis = sender.value
spiralView.set_needs_display()
def switchDrawDotsChanged(sender):
spiralView = v['spiralView']
spiralView.drawDots = sender.value
v['labelDrawNumbers'].hidden = not sender.value
v['switchDrawNumbers'].hidden = not sender.value
v['labelHilitePrimes'].hidden = not sender.value
v['switchHilitePrimes'].hidden = not sender.value
if sender.value: # es wurde EINgeschaltet
# wenn HilitePrimes aus ist, darf PrimesOnly nicht sichtbar gemacht werden
if spiralView.hilitePrimes:
v['labelPrimesOnly'].hidden = not sender.value # False
v['switchPrimesOnly'].hidden = not sender.value # False
else: # es wurde AUSgeschaltet
# dann muss PrimesOnly immer auch ausgeblendet werden
v['labelPrimesOnly'].hidden = not sender.value # False
v['switchPrimesOnly'].hidden = not sender.value # False
spiralView.set_needs_display()
def switchDrawNumbersChanged(sender):
spiralView = v['spiralView']
spiralView.drawNumbers = sender.value
spiralView.set_needs_display()
def switchHilitePrimesChanged(sender):
spiralView = v['spiralView']
spiralView.hilitePrimes = sender.value
v['labelPrimesOnly'].hidden = not sender.value
v['switchPrimesOnly'].hidden = not sender.value
if not spiralView.hilitePrimes:
spiralView.primesOnly = False
v['switchPrimesOnly'].value = False
spiralView.set_needs_display()
def switchDrawSpiralChanged(sender):
spiralView = v['spiralView']
spiralView.drawSpiral = sender.value
spiralView.set_needs_display()
def switchPrimesOnlyChanged(sender):
spiralView = v['spiralView']
spiralView.primesOnly = sender.value
spiralView.set_needs_display()
def switchDrawCurveChanged(sender):
spiralView = v['spiralView']
spiralView.drawCurve = sender.value
toggleCurveGUI(not spiralView.drawCurve)
spiralView.set_needs_display()
#--- Buttons ----------------------------------------------
def buttonMetawopsTapped(sender):
webbrowser.open("safari-http://twitter.com/metawops")
# Show the settings dialog
def settingsButtonTapped(sender):
settingsView = ui.load_view('NumberSpiralsSettings.pyui')
spiralView = v['spiralView']
settingsView['sliderDotSize'].value = (spiralView.dotSize-1.0)/9.0
settingsView['labelDotSize'].text = "{:.0f}".format(spiralView.dotSize)
settingsView['sliderFontSize'].value = (spiralView.numberFont[1]-8.0)/23.0
settingsView['labelFontSize'].text = "{:.0f}".format(spiralView.numberFont[1])
settingsView.present('sheet')
#--- GUI helpers
def toggleCurveGUI(hideBool):
v['labelA'].hidden = hideBool
v['labelB'].hidden = hideBool
v['labelC'].hidden = hideBool
v['sliderA'].hidden = hideBool
v['sliderB'].hidden = hideBool
v['sliderC'].hidden = hideBool
v['textfieldA'].hidden = hideBool
v['textfieldB'].hidden = hideBool
v['textfieldC'].hidden = hideBool
#--- MAIN
if (machine()[:3] == 'iPa'):
v = ui.load_view('NumberSpirals.pyui')
spiralView = v['spiralView']
v['sliderSpacing'].value = (spiralView.spacing)/spiralView.maxSpacing
v['labelSpacing'].text = "{:.1f}".format(spiralView.spacing)
v['sliderTurns'].value = (spiralView.turns)/spiralView.maxTurns
v['labelTurns'].text = "{:.0f}".format(spiralView.turns)
v['switchAutoSpacing'].value = spiralView.autoSpacing
v['sliderSpacing'].hidden = spiralView.autoSpacing
v['switchDrawAxis'].value = spiralView.drawAxis
v['switchDrawDots'].value = spiralView.drawDots
v['switchDrawNumbers'].value = spiralView.drawNumbers
v['switchHilitePrimes'].value = spiralView.hilitePrimes
v['switchDrawSpiral'].value = spiralView.drawSpiral
v['switchPrimesOnly'].value = spiralView.primesOnly
if (not spiralView.primesOnly):
v['labelPrimesOnly'].hidden = True
v['switchPrimesOnly'].hidden = True
v['switchDrawCurve'].value = spiralView.drawCurve
if (not spiralView.drawCurve):
toggleCurveGUI(True)
v['textfieldA'].delegate = CurveParamTextFieldDelegate()
v['textfieldB'].delegate = CurveParamTextFieldDelegate()
v['textfieldC'].delegate = CurveParamTextFieldDelegate()
v['sliderA'].value = spiralView.curveParamA / spiralView.maxA
v['textfieldA'].text = "{:.0f}".format(spiralView.curveParamA)
v['sliderB'].value = spiralView.curveParamB / spiralView.maxB
v['textfieldB'].text = "{:.0f}".format(spiralView.curveParamB)
v['sliderC'].value = spiralView.curveParamC / spiralView.maxC
v['textfieldC'].text = "{:.0f}".format(spiralView.curveParamC)
v.present('full_screen')
else:
print('Sorry, Number Spiral Explorer is iPad-only.')
[
{
"selected" : false,
"frame" : "{{0, 0}, {1270, 970}}",
"class" : "View",
"nodes" : [
{
"selected" : false,
"frame" : "{{964, 193}, {293, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"continuous" : true,
"action" : "sliderSpacingChanged",
"frame" : "{{378, 402}, {200, 34}}",
"class" : "Slider",
"uuid" : "14BEF107-92A6-4490-B837-763FA4EEFA9A",
"value" : 0.5,
"name" : "sliderSpacing"
}
},
{
"selected" : false,
"frame" : "{{964, 161}, {134, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System>",
"frame" : "{{403, 403}, {150, 32}}",
"uuid" : "1C1C0234-66D2-4791-8726-3C44A1B3AB1E",
"text" : "Spacing",
"alignment" : "left",
"class" : "Label",
"font_size" : 18,
"name" : "label1"
}
},
{
"selected" : false,
"frame" : "{{6, 6}, {950, 950}}",
"class" : "View",
"nodes" : [
],
"attributes" : {
"border_width" : 1,
"flex" : "WH",
"custom_class" : "numberSpiralView",
"frame" : "{{428, 369}, {100, 100}}",
"border_color" : "RGBA(0.563679,0.563679,0.563679,1.000000)",
"corner_radius" : 12,
"class" : "View",
"uuid" : "75147734-1377-4973-9391-22C9D76924ED",
"background_color" : "RGBA(0.839623,0.839623,0.839623,1.000000)",
"name" : "spiralView"
}
},
{
"selected" : false,
"frame" : "{{1129, 169}, {128, 24}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 14,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "C50B6C14-9F0D-439C-970C-7CECC9187813",
"text" : "Label",
"alignment" : "right",
"class" : "Label",
"name" : "labelSpacing",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{964, 112}, {293, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "sliderTurnsChanged",
"continuous" : true,
"frame" : "{{535, 468}, {200, 34}}",
"class" : "Slider",
"uuid" : "E4B50AFE-2925-4B56-85CC-E46490EB0A40",
"value" : 0.5,
"name" : "sliderTurns"
}
},
{
"selected" : false,
"frame" : "{{964, 82}, {150, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "2DB32B3C-ED81-4B50-B1D0-D2EC55727CB5",
"text" : "Turns",
"alignment" : "left",
"class" : "Label",
"name" : "label2",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1129, 90}, {128, 24}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 14,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "DEDEBEE9-77AD-4FC8-8AF2-CB8E1EB46845",
"text" : "Label",
"alignment" : "right",
"class" : "Label",
"name" : "labelTurns",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1206, 226}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "switchAutoSpacingChanged",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "4740F7C5-9468-4BDA-90A2-B47B496A34A7",
"value" : true,
"name" : "switchAutoSpacing"
}
},
{
"selected" : false,
"frame" : "{{964, 226}, {234, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "F96998B1-835F-4478-9AE3-F817EB5BFD3F",
"text" : "Auto Spacing",
"alignment" : "left",
"class" : "Label",
"name" : "label3",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1206, 324}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "switchDrawAxisChanged",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "F5AEC3CB-FEB1-436F-8116-4EE3D1343BDD",
"value" : false,
"name" : "switchDrawAxis"
}
},
{
"selected" : false,
"frame" : "{{964, 324}, {234, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "964EFD22-0953-4EA4-8ABF-1459579222DC",
"text" : "Draw Axis",
"alignment" : "left",
"class" : "Label",
"name" : "label4",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1206, 363}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"action" : "switchDrawDotsChanged",
"flex" : "L",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "F9857D63-4F6C-4053-ADB4-F6D539630A05",
"value" : true,
"name" : "switchDrawDots"
}
},
{
"selected" : false,
"frame" : "{{964, 364}, {234, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "14622C3D-4B99-4563-9F65-72A5B07CA096",
"text" : "Draw Number Dots",
"alignment" : "left",
"class" : "Label",
"name" : "label5",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1206, 402}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "switchDrawNumbersChanged",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "9202C51F-0137-4A96-A405-4799F2DA3405",
"value" : true,
"name" : "switchDrawNumbers"
}
},
{
"selected" : false,
"frame" : "{{988, 401}, {210, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "D41E47BB-0A30-4FE8-B41E-F4704967B279",
"text" : "Draw Numbers",
"alignment" : "left",
"class" : "Label",
"name" : "labelDrawNumbers",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1206, 441}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "switchHilitePrimesChanged",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "CE8DE121-E544-48D2-9967-CC9D6045FF35",
"value" : false,
"name" : "switchHilitePrimes"
}
},
{
"selected" : false,
"frame" : "{{988, 440}, {210, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System>",
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "DF02276E-89B9-4AAB-A6B5-AD9D194F49E0",
"text" : "Highlight Primes",
"alignment" : "left",
"class" : "Label",
"name" : "labelHilitePrimes",
"font_size" : 18
}
},
{
"selected" : false,
"frame" : "{{964, 6}, {219, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System-Bold>",
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "B4803AD5-FA89-4CCB-A068-F1BAD7D6C3B8",
"text" : "Number Spiral Explorer",
"alignment" : "left",
"class" : "Label",
"name" : "label7",
"font_size" : 20
}
},
{
"selected" : false,
"frame" : "{{964, 37}, {125, 27}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"name" : "label8",
"font_name" : "<System>",
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "9BD4F8BC-8DEF-466C-B4AC-BFF12F056C6B",
"text" : "By Stefan Wolfrum,",
"alignment" : "left",
"class" : "Label",
"font_size" : 14,
"text_color" : "RGBA(0.507075,0.507075,0.507075,1.000000)"
}
},
{
"selected" : false,
"frame" : "{{1183, 9}, {30, 27}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"name" : "label9",
"font_name" : "<System>",
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "B65E8AF8-10B3-41D1-AC37-D3D21A8070B5",
"text" : "v0.9",
"alignment" : "right",
"class" : "Label",
"font_size" : 14,
"text_color" : "RGBA(0.507075,0.507075,0.507075,1.000000)"
}
},
{
"selected" : false,
"frame" : "{{1093, 37}, {80, 27}}",
"class" : "Button",
"nodes" : [
],
"attributes" : {
"action" : "buttonMetawopsTapped",
"flex" : "L",
"frame" : "{{595, 469}, {80, 32}}",
"title" : "@metawops",
"class" : "Button",
"uuid" : "7BB1F2E8-B4DA-47E9-A528-0E41E6133C10",
"font_size" : 14,
"name" : "button1"
}
},
{
"selected" : false,
"frame" : "{{1206, 285}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "switchDrawSpiralChanged",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "5DFAD3BE-A4E8-464E-9DE4-929AEC79B54D",
"value" : true,
"name" : "switchDrawSpiral"
}
},
{
"selected" : false,
"frame" : "{{964, 285}, {234, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System>",
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "37B0504A-6CE1-4373-B0B1-07DEDF9D3486",
"text" : "Draw Spiral",
"alignment" : "left",
"class" : "Label",
"name" : "label10",
"font_size" : 18
}
},
{
"selected" : false,
"frame" : "{{1012, 480}, {186, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System>",
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "3DDAEE99-08E8-4F53-93FD-0D27F306E136",
"text" : "Primes only",
"alignment" : "left",
"class" : "Label",
"font_size" : 18,
"name" : "labelPrimesOnly"
}
},
{
"selected" : false,
"frame" : "{{1206, 481}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"action" : "switchPrimesOnlyChanged",
"flex" : "L",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "563091AE-FD20-45DF-8F1B-61E5BA64C613",
"value" : true,
"name" : "switchPrimesOnly"
}
},
{
"selected" : false,
"frame" : "{{1206, 533}, {51, 31}}",
"class" : "Switch",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"action" : "switchDrawCurveChanged",
"frame" : "{{610, 470}, {51, 31}}",
"class" : "Switch",
"uuid" : "BD03F69A-08CA-4FA4-BC7B-7C2B49F87AA2",
"value" : true,
"name" : "switchDrawCurve"
}
},
{
"selected" : false,
"frame" : "{{964, 533}, {180, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "E0E80932-2017-44F2-8FB6-13F34535B816",
"text" : "Draw Curve an²+bn+c",
"alignment" : "left",
"class" : "Label",
"name" : "label11",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{998, 573}, {200, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"continuous" : true,
"action" : "sliderAchanged",
"frame" : "{{535, 468}, {200, 34}}",
"class" : "Slider",
"uuid" : "4915C6D8-0D64-4CEE-9564-F3765E67203F",
"value" : 0.5,
"name" : "sliderA"
}
},
{
"selected" : false,
"frame" : "{{964, 573}, {37, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "1F206667-B1F1-49CB-9790-0DF0307135DA",
"text" : "a",
"alignment" : "left",
"class" : "Label",
"name" : "labelA",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{998, 608}, {200, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"continuous" : true,
"action" : "sliderBchanged",
"frame" : "{{535, 468}, {200, 34}}",
"class" : "Slider",
"uuid" : "2E66192C-5DBC-4709-AA17-0A94C26FA9B8",
"value" : 0.5,
"name" : "sliderB"
}
},
{
"selected" : false,
"frame" : "{{964, 608}, {37, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "3200D93A-3079-454A-91FF-EB69317CE6E2",
"text" : "b",
"alignment" : "left",
"class" : "Label",
"name" : "labelB",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{964, 643}, {37, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_size" : 18,
"frame" : "{{560, 469}, {150, 32}}",
"uuid" : "E6AEA25B-08AE-4E97-9603-FAB33BC32EC7",
"text" : "c",
"alignment" : "left",
"class" : "Label",
"name" : "labelC",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{998, 643}, {200, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"continuous" : true,
"action" : "sliderCchanged",
"frame" : "{{535, 468}, {200, 34}}",
"class" : "Slider",
"uuid" : "82683FFC-D9A7-4ACE-AF11-2BBEB1FFF2A4",
"value" : 0.5,
"name" : "sliderC"
}
},
{
"selected" : false,
"frame" : "{{1200, 573}, {57, 32}}",
"class" : "TextField",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System>",
"frame" : "{{535, 469}, {200, 32}}",
"spellchecking_type" : "default",
"class" : "TextField",
"uuid" : "E0D36685-CC65-447D-B528-D67E3B190DB3",
"alignment" : "left",
"autocorrection_type" : "default",
"name" : "textfieldA",
"font_size" : 17
}
},
{
"selected" : false,
"frame" : "{{1200, 608}, {57, 32}}",
"class" : "TextField",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"name" : "textfieldB",
"frame" : "{{535, 469}, {200, 32}}",
"spellchecking_type" : "default",
"class" : "TextField",
"uuid" : "E0D36685-CC65-447D-B528-D67E3B190DB3",
"alignment" : "left",
"autocorrection_type" : "default",
"font_size" : 17,
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{1200, 644}, {57, 32}}",
"class" : "TextField",
"nodes" : [
],
"attributes" : {
"flex" : "L",
"font_name" : "<System>",
"frame" : "{{535, 469}, {200, 32}}",
"spellchecking_type" : "default",
"class" : "TextField",
"uuid" : "E0D36685-CC65-447D-B528-D67E3B190DB3",
"alignment" : "left",
"autocorrection_type" : "default",
"font_size" : 17,
"name" : "textfieldC"
}
},
{
"selected" : true,
"frame" : "{{1226, 36}, {30, 30}}",
"class" : "Button",
"nodes" : [
],
"attributes" : {
"action" : "settingsButtonTapped",
"flex" : "L",
"font_size" : 15,
"frame" : "{{595, 469}, {80, 32}}",
"title" : "",
"class" : "Button",
"uuid" : "5393B48F-0E0B-417B-ABF8-A6919B99D3F0",
"name" : "buttonSettings",
"image_name" : "iob:ios7_gear_outline_32"
}
}
],
"attributes" : {
"name" : "Number Spirals",
"enabled" : true,
"border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)",
"background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)",
"tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)",
"flex" : ""
}
}
]
[
{
"selected" : false,
"frame" : "{{0, 0}, {320, 320}}",
"class" : "View",
"nodes" : [
{
"selected" : true,
"frame" : "{{6, 80}, {308, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "W",
"action" : "sliderSettingsDotSizeChanged",
"continuous" : true,
"frame" : "{{60, 143}, {200, 34}}",
"class" : "Slider",
"uuid" : "902B44EF-0E87-4DCC-B201-A3754D776C1B",
"value" : 0.5,
"name" : "sliderDotSize"
}
},
{
"selected" : false,
"frame" : "{{6, 40}, {150, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"font_name" : "<System>",
"frame" : "{{85, 144}, {150, 32}}",
"uuid" : "63950743-4086-477D-B6FD-B3432D88175C",
"text" : "Dots' size",
"alignment" : "left",
"class" : "Label",
"font_size" : 18,
"name" : "label1"
}
},
{
"selected" : false,
"frame" : "{{6, 182}, {308, 34}}",
"class" : "Slider",
"nodes" : [
],
"attributes" : {
"flex" : "W",
"action" : "sliderSettingsFontSizeChanged",
"continuous" : true,
"frame" : "{{60, 143}, {200, 34}}",
"uuid" : "902B44EF-0E87-4DCC-B201-A3754D776C1B",
"class" : "Slider",
"value" : 0.5,
"name" : "sliderFontSize"
}
},
{
"selected" : false,
"frame" : "{{6, 142}, {150, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"font_size" : 18,
"frame" : "{{85, 144}, {150, 32}}",
"uuid" : "63950743-4086-477D-B6FD-B3432D88175C",
"text" : "Font size",
"alignment" : "left",
"class" : "Label",
"name" : "label1",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{6, 6}, {308, 29}}",
"class" : "SegmentedControl",
"nodes" : [
],
"attributes" : {
"class" : "SegmentedControl",
"frame" : "{{100, 146}, {120, 29}}",
"uuid" : "63185922-A713-49C8-9B7F-84FAB934D57F",
"segments" : "Sizes|Colors|Other",
"name" : "segmentedcontrol1",
"flex" : "LR"
}
},
{
"selected" : false,
"frame" : "{{243, 142}, {71, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"font_size" : 18,
"frame" : "{{85, 144}, {150, 32}}",
"uuid" : "792438F5-AB07-4B7F-A14E-8833E97C85F9",
"text" : "Label",
"alignment" : "right",
"class" : "Label",
"name" : "labelFontSize",
"font_name" : "<System>"
}
},
{
"selected" : false,
"frame" : "{{243, 43}, {71, 32}}",
"class" : "Label",
"nodes" : [
],
"attributes" : {
"font_name" : "<System>",
"frame" : "{{85, 144}, {150, 32}}",
"uuid" : "792438F5-AB07-4B7F-A14E-8833E97C85F9",
"text" : "Label",
"alignment" : "right",
"class" : "Label",
"name" : "labelDotSize",
"font_size" : 18
}
}
],
"attributes" : {
"flex" : "",
"enabled" : true,
"background_color" : "RGBA(1.000000,1.000000,1.000000,1.000000)",
"name" : "Preferences",
"tint_color" : "RGBA(0.000000,0.478000,1.000000,1.000000)",
"border_color" : "RGBA(0.000000,0.000000,0.000000,1.000000)"
}
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment