dedalus 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +7 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +1 -0
  6. data/ChangeLog.md +4 -0
  7. data/Gemfile +11 -0
  8. data/LICENSE.txt +20 -0
  9. data/README.md +135 -0
  10. data/Rakefile +42 -0
  11. data/bin/dedalus +20 -0
  12. data/dedalus.gemspec +60 -0
  13. data/features/.gitkeep +0 -0
  14. data/features/dedalus.feature +1 -0
  15. data/features/step_definitions/.gitkeep +0 -0
  16. data/features/step_definitions/dedalus_steps.rb +1 -0
  17. data/gemspec.yml +20 -0
  18. data/lib/dedalus/app_view_composer.rb +60 -0
  19. data/lib/dedalus/application_view.rb +48 -0
  20. data/lib/dedalus/elements/heading.rb +13 -0
  21. data/lib/dedalus/elements/icon.rb +21 -0
  22. data/lib/dedalus/elements/image.rb +53 -0
  23. data/lib/dedalus/elements/paragraph.rb +13 -0
  24. data/lib/dedalus/elements/text.rb +44 -0
  25. data/lib/dedalus/elements.rb +78 -0
  26. data/lib/dedalus/palette.rb +89 -0
  27. data/lib/dedalus/pattern_library/application.rb +140 -0
  28. data/lib/dedalus/pattern_library/application_view.rb +28 -0
  29. data/lib/dedalus/pattern_library/library_view.rb +7 -0
  30. data/lib/dedalus/pattern_library/models/library.rb +10 -0
  31. data/lib/dedalus/pattern_library/models/library_item.rb +11 -0
  32. data/lib/dedalus/pattern_library/models/library_section.rb +26 -0
  33. data/lib/dedalus/pattern_library/molecules/library_item_example.rb +50 -0
  34. data/lib/dedalus/pattern_library/molecules/library_section_tab.rb +62 -0
  35. data/lib/dedalus/pattern_library/molecules/periodic_table.rb +32 -0
  36. data/lib/dedalus/pattern_library/molecules/periodic_table_entry.rb +70 -0
  37. data/lib/dedalus/pattern_library/organisms/app_footer.rb +37 -0
  38. data/lib/dedalus/pattern_library/organisms/app_header.rb +36 -0
  39. data/lib/dedalus/pattern_library/organisms/app_sidebar.rb +29 -0
  40. data/lib/dedalus/pattern_library/organisms/library_entry.rb +64 -0
  41. data/lib/dedalus/pattern_library/screens/app_screen.rb +22 -0
  42. data/lib/dedalus/pattern_library/templates/app_template.rb +94 -0
  43. data/lib/dedalus/pattern_library.rb +1 -0
  44. data/lib/dedalus/version.rb +4 -0
  45. data/lib/dedalus/view_traversal.rb +129 -0
  46. data/lib/dedalus.rb +40 -0
  47. data/media/icons/arrow_cursor.png +0 -0
  48. data/media/icons/atom.png +0 -0
  49. data/media/icons/hive.png +0 -0
  50. data/media/icons/house.png +0 -0
  51. data/media/icons/molecule.png +0 -0
  52. data/media/icons/paramecium.png +0 -0
  53. data/spec/dedalus_spec.rb +28 -0
  54. data/spec/spec_helper.rb +4 -0
  55. metadata +226 -0
@@ -0,0 +1,89 @@
1
+ module Dedalus
2
+ class Color
3
+ attr_accessor :red, :green, :blue, :alpha
4
+
5
+ def initialize(red,green,blue,alpha=255)
6
+ @red = red
7
+ @green = green
8
+ @blue = blue
9
+ @alpha = alpha
10
+ end
11
+
12
+ # def mix(other_color)
13
+ # Color.new(
14
+ # (red+other_color.red/2),
15
+ # (green+other_color.green/2),
16
+ # (blue+other_color.blue/2)
17
+ # )
18
+ # end
19
+
20
+ def darken(ratio=0.90)
21
+ Color.new(red*ratio,green*ratio,blue*ratio)
22
+ end
23
+
24
+ def lighten(ratio=1.10)
25
+ Color.new(red*ratio,green*ratio,blue*ratio)
26
+ end
27
+
28
+ def to_gosu
29
+ Gosu::Color.rgba(red, green, blue, alpha)
30
+ end
31
+ end
32
+
33
+ class ColorPalette
34
+ attr_accessor :red, :green, :blue, :yellow, :purple, :gray, :white
35
+ def initialize(red:, green:, blue:, yellow:, purple:, gray:, white: Color.new(240,240,240))
36
+ @red = red
37
+ @green = green
38
+ @blue = blue
39
+ @yellow = yellow
40
+ @purple = purple
41
+ @gray = gray
42
+ @white = white
43
+ end
44
+
45
+ def decode_color(color)
46
+ return color if color.is_a?(Dedalus::Color)
47
+
48
+ case color
49
+ when 'red' then red
50
+ when 'lightred' then red.lighten
51
+ when 'darkred' then red.darken
52
+
53
+ when 'green' then green
54
+ when 'lightgreen' then green.lighten
55
+ when 'darkgreen' then green.darken
56
+
57
+ when 'blue' then blue
58
+ when 'lightblue' then blue.lighten
59
+ when 'darkblue' then blue.darken
60
+
61
+ when 'yellow' then yellow
62
+ when 'lightyellow' then yellow.lighten
63
+ when 'darkyellow' then yellow.darken
64
+
65
+ when 'gray' then gray
66
+ when 'lightgray' then gray.lighten
67
+ when 'darkgray' then gray.darken
68
+
69
+ when 'purple' then purple
70
+ when 'lightpurple' then purple.lighten
71
+ when 'darkpurple' then purple.darken
72
+
73
+ else
74
+ raise "Unknown color string given to #{self.class.name}#decode_color: #{color}"
75
+ end
76
+ end
77
+ end
78
+
79
+ DesaturatedPalette = ColorPalette.new(
80
+ red: Color.new(140, 100, 100),
81
+ green: Color.new(100, 140, 100),
82
+ blue: Color.new(100, 100, 140),
83
+ yellow: Color.new(150, 140, 100),
84
+ purple: Color.new(140, 100, 140),
85
+ gray: Color.new(80, 80, 80)
86
+ )
87
+
88
+ Palette = DesaturatedPalette
89
+ end
@@ -0,0 +1,140 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class Application < Joyce::Application
4
+ viewed_with ApplicationView
5
+ include Models
6
+
7
+ def click
8
+ p [ :app_click ]
9
+ view.click
10
+ end
11
+
12
+ def setup(module_to_search:)
13
+ create_library(module_to_search)
14
+ end
15
+
16
+ def find_descendants_of(klass, module_to_search)
17
+ ObjectSpace.each_object(Class).select { |k| k < klass && find_descendants_of(k, module_to_search).count.zero? && k.name.deconstantize == module_to_search.name }
18
+ end
19
+
20
+ def create_library(module_to_search)
21
+ library = Library.create(name: "Dedalus Pattern Library")
22
+
23
+ atom_section = library.create_library_section(
24
+ name: "Atoms",
25
+ icon: :atom,
26
+ color: 'darkred',
27
+ about: "Components that can't be split further"
28
+ )
29
+
30
+ atom_classes = find_descendants_of(Dedalus::Atom, module_to_search)
31
+ atom_section.build_items_from_classes(atom_classes, kind: 'atom')
32
+
33
+ molecules_section = library.create_library_section(
34
+ name: "Molecules",
35
+ icon: :molecule,
36
+ color: 'yellow',
37
+ about: "Simple compounds of a few atoms"
38
+ )
39
+
40
+ molecule_classes = find_descendants_of(Dedalus::Molecule, module_to_search)
41
+ molecules_section.build_items_from_classes(molecule_classes, kind: 'molecule')
42
+
43
+ organism_section = library.create_library_section({
44
+ name: "Organisms",
45
+ icon: :paramecium,
46
+ color: 'green',
47
+ about: "Highly-complex assemblages of molecules"
48
+ })
49
+
50
+ organism_classes = find_descendants_of(Dedalus::Organism, module_to_search)
51
+ organism_section.build_items_from_classes(organism_classes, kind: 'organism')
52
+
53
+ template_section = library.create_library_section({
54
+ name: "Templates",
55
+ icon: :hive,
56
+ color: 'blue',
57
+ about: "Assembled screens with placeholders"})
58
+
59
+ template_section.create_library_item({
60
+ name: "Library Template",
61
+ item_class_name: 'Dedalus::PatternLibrary::ApplicationTemplate',
62
+ description: "ui library app template",
63
+ example_data: ApplicationTemplate.example_data
64
+ })
65
+
66
+ # just manually create a view from models for now...
67
+ library_data = serialize_library(library)
68
+ library_view = LibraryView.create(library_data)
69
+ view.library_view = library_view
70
+ end
71
+
72
+ def serialize_library(library)
73
+ {
74
+ library_name: library.name,
75
+
76
+ library_sections: [welcome_section] + library.library_sections.map do |section|
77
+ {
78
+ title: section.name,
79
+ subtitle: section.about,
80
+ color: section.color,
81
+ items: section.library_items.map do |item|
82
+ {
83
+ name: item.name,
84
+ kind: item.kind,
85
+ color: section.color,
86
+ description: item.description,
87
+ item_class_name: item.item_class_name,
88
+ item_data: item.example_data
89
+ }
90
+ end
91
+ }
92
+ end,
93
+
94
+ library_section_tabs: [welcome_tab] + library.library_sections.map do |section|
95
+ {
96
+ name: section.name,
97
+ icon: section.icon,
98
+ description: section.about,
99
+ section_color: section.color
100
+ }
101
+ end,
102
+
103
+ library_items: all_library_items
104
+ }
105
+ end
106
+
107
+ def welcome_tab
108
+ {
109
+ name: "Welcome",
110
+ icon: :house,
111
+ description: "About the Library",
112
+ section_color: "darkgray"
113
+ }
114
+ end
115
+
116
+ def welcome_section
117
+ {
118
+ title: "Welcome",
119
+ subtitle: "About the Dedalus library",
120
+ color: 'darkgray',
121
+ show_table: true,
122
+ items: all_library_items
123
+ }
124
+ end
125
+
126
+ def all_library_items
127
+ LibraryItem.all.map do |item|
128
+ {
129
+ name: item.name,
130
+ kind: item.kind,
131
+ color: item.color,
132
+ description: item.description,
133
+ item_class_name: item.item_class_name,
134
+ item_data: item.example_data
135
+ }
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,28 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class ApplicationView < Dedalus::ApplicationView
4
+ attr_accessor :library_view
5
+
6
+ def app_screen
7
+ ApplicationScreen.new(app_template).hydrate(
8
+ library_section_tabs: library_view.library_section_tabs,
9
+ current_entry_name: current_entry_name,
10
+ library_sections: library_view.library_sections,
11
+ library_items: library_view.library_items
12
+ )
13
+ end
14
+
15
+ def app_template
16
+ ApplicationTemplate.new
17
+ end
18
+
19
+ def current_entry_name
20
+ @current_entry_name ||= "Welcome"
21
+ end
22
+
23
+ def route_to(section_name)
24
+ @current_entry_name = section_name
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class LibraryView < Metacosm::View
4
+ attr_accessor :library_name, :library_section_tabs, :library_sections, :library_items
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ module Models
4
+ class Library < Metacosm::Model
5
+ attr_accessor :name
6
+ has_many :library_sections
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ module Models
4
+ class LibraryItem < Metacosm::Model
5
+ attr_accessor :name, :color, :kind, :description
6
+ attr_accessor :item_class_name, :example_data
7
+ belongs_to :library_section
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ module Models
4
+ class LibrarySection < Metacosm::Model
5
+ attr_accessor :name, :about, :description, :icon, :color
6
+ belongs_to :library
7
+ has_many :library_items
8
+
9
+ def build_items_from_classes(klasses, kind:)
10
+ klasses.each do |klass|
11
+ item_name = klass.name.to_s
12
+
13
+ create_library_item(
14
+ name: item_name.demodulize.titleize,
15
+ color: self.color,
16
+ kind: kind,
17
+ item_class_name: item_name,
18
+ description: klass.description,
19
+ example_data: klass.example_data
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class LibraryItemExample < Dedalus::Molecule
4
+ attr_accessor :name
5
+ attr_accessor :item_class_name
6
+ attr_accessor :item_data
7
+ attr_accessor :kind
8
+ attr_accessor :color
9
+
10
+ def show
11
+ [
12
+ Elements::Paragraph.new(text: "EXAMPLE", scale: 0.5, height_percent: 0.05, background_color: background_color.darken),
13
+ item,
14
+ Elements::Paragraph.new(text: item_data, scale: 0.7, background_color: Palette.decode_color('darkgray'), padding: 10)
15
+ ]
16
+ end
17
+
18
+ def item
19
+ item_class_name.constantize.new(item_data)
20
+ end
21
+
22
+ def width_percent
23
+ 0.6
24
+ end
25
+
26
+ def background_color
27
+ if color
28
+ Palette.decode_color(color).darken
29
+ else
30
+ Palette.gray
31
+ end
32
+ end
33
+
34
+ def self.description
35
+ "an example of a pattern"
36
+ end
37
+
38
+ def self.example_data
39
+ {
40
+ name: "Paragraph",
41
+ description: "fake library item molecule",
42
+ item_class_name: 'Dedalus::Elements::Paragraph',
43
+ item_data: { text: "Hi there!" },
44
+ color: 'red', #Palette.red,
45
+ kind: 'Atom'
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,62 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class LibrarySectionTab < Dedalus::Molecule
4
+ attr_accessor :icon, :name, :description, :scale, :highlight, :section_color
5
+
6
+ def show
7
+ [[
8
+ icon_element, [ title_element,
9
+ description_element ]
10
+ ]]
11
+ end
12
+
13
+ def hover
14
+ p [ :hovering_on, section: name ]
15
+ @scale = 0.2
16
+ end
17
+
18
+ def background_color
19
+ bg = Palette.decode_color(section_color)
20
+ self.highlight ? bg.lighten : bg
21
+ end
22
+
23
+ def click
24
+ view.route_to(name)
25
+ end
26
+
27
+ def scale
28
+ @scale ||= 0.0
29
+ end
30
+
31
+ def height
32
+ @height ||= 80
33
+ end
34
+
35
+ def icon_element
36
+ Elements::Icon.for(icon, padding: 16)
37
+ end
38
+
39
+ def title_element
40
+ Elements::Heading.new(text: name, scale: 1.8 + scale)
41
+ end
42
+
43
+ def description_element
44
+ Elements::Paragraph.new(text: description)
45
+ end
46
+
47
+ def self.description
48
+ "navigational tab"
49
+ end
50
+
51
+ def self.example_data
52
+ {
53
+ icon: :house,
54
+ name: "Welcome",
55
+ description: "Hello world (links to Welcome)",
56
+ highlight: false,
57
+ section_color: 'gray'
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,32 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class PeriodicTable < Dedalus::Molecule
4
+ attr_accessor :elements
5
+
6
+ def show
7
+ self.element_groups.map do |_, grouped_elements|
8
+ grouped_elements.map do |name:, color:, kind:, **|
9
+ PeriodicTableEntry.new(
10
+ element_name: name,
11
+ color: color,
12
+ kind: kind,
13
+ scale: 0.5
14
+ )
15
+ end
16
+ end
17
+ end
18
+
19
+ def element_groups
20
+ elements.group_by { |elem| elem[:kind] }
21
+ end
22
+
23
+ def self.description
24
+ "A collection of elements"
25
+ end
26
+
27
+ def self.example_data
28
+ { elements: Array.new(4) { LibraryItemExample.example_data } }
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,70 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class PeriodicTableEntry < Dedalus::Molecule
4
+ attr_accessor :element_name
5
+ attr_accessor :kind
6
+ attr_accessor :color
7
+ attr_accessor :scale
8
+
9
+ def show
10
+ [
11
+ Elements::Heading.new(text: abbreviation, scale: 6.0 * scale),
12
+ Elements::Paragraph.new(text: element_name, scale: scale),
13
+ Elements::Paragraph.new(text: kind, scale: 0.6 * scale)
14
+ ]
15
+ end
16
+
17
+ def scale
18
+ @scale ||= 1.0
19
+ end
20
+
21
+ def abbreviation
22
+ if element_name.match(/ /) #split(" ").count > 0
23
+ element_name.split(" ").map(&:first).join.capitalize
24
+ else
25
+ element_name.slice(0,2).capitalize
26
+ end
27
+ end
28
+
29
+ def click
30
+ view.route_to(element_name)
31
+ end
32
+
33
+ def margin
34
+ 15 * scale
35
+ end
36
+
37
+ def padding
38
+ 20 * scale
39
+ end
40
+
41
+ def width
42
+ 230 * scale
43
+ end
44
+
45
+ def height
46
+ 250 * scale
47
+ end
48
+
49
+ def background_color
50
+ if color
51
+ c = Palette.decode_color(color) if color.is_a?(String)
52
+ c.darken
53
+ else
54
+ Palette.gray
55
+ end
56
+ end
57
+
58
+ def self.description
59
+ "a high-level view of an element"
60
+ end
61
+
62
+ def self.example_data
63
+ {
64
+ element_abbreviation: "Pa",
65
+ element_name: "Paragraph"
66
+ }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,37 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class ApplicationFooter < Dedalus::Organism
4
+ attr_accessor :joyce_version, :dedalus_version, :company, :copyright
5
+
6
+ def show
7
+ [ footer_message ]
8
+ end
9
+
10
+ def padding
11
+ 20
12
+ end
13
+
14
+ def self.description
15
+ "An application footer"
16
+ end
17
+
18
+ def self.example_data
19
+ {
20
+ joyce_version: "x.y.z",
21
+ dedalus_version: "a.b.c",
22
+ company: "Hello LLC",
23
+ copyright: "All rights reserved"
24
+ }
25
+ end
26
+
27
+ private
28
+ def footer_message
29
+ @footer_message ||= Elements::Paragraph.new(text: assemble_text, scale: 0.5)
30
+ end
31
+
32
+ def assemble_text
33
+ "Powered by Dedalus v#{dedalus_version} and Joyce v#{joyce_version}. Copyright #{company} #{copyright}. All rights reserved."
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class ApplicationHeader < Dedalus::Organism
4
+ attr_accessor :title, :subtitle
5
+
6
+ def show
7
+ [
8
+ heading,
9
+ subheading
10
+ ]
11
+ end
12
+
13
+ def padding
14
+ 20
15
+ end
16
+
17
+ def self.description
18
+ "An application header"
19
+ end
20
+
21
+ def self.example_data
22
+ { title: "Fake app", description: "Hello world" }
23
+ end
24
+
25
+ private
26
+ def heading
27
+ @heading ||= Elements::Heading.new(text: title)
28
+ end
29
+
30
+ def subheading
31
+ @subheading ||= Elements::Heading.new(text: subtitle, scale: 0.75)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,29 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class ApplicationSidebar < Dedalus::Organism
4
+ attr_accessor :library_section_tab_molecules
5
+
6
+ def show
7
+ self.library_section_tab_molecules
8
+ end
9
+
10
+ def padding
11
+ 0
12
+ end
13
+
14
+ def self.description
15
+ "A sidebar for an application"
16
+ end
17
+
18
+ def self.example_data
19
+ {
20
+ library_section_tab_molecules: [
21
+ LibrarySectionTab.new(LibrarySectionTab.example_data),
22
+ LibrarySectionTab.new(LibrarySectionTab.example_data),
23
+ LibrarySectionTab.new(LibrarySectionTab.example_data)
24
+ ]
25
+ }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ module Dedalus
2
+ module PatternLibrary
3
+ class LibraryEntry < Dedalus::Organism
4
+ attr_accessor :title, :subtitle, :description, :color, :items, :item, :show_table
5
+
6
+ def self.from_item(item)
7
+ new(title: item[:name], subtitle: item[:description], item: item)
8
+ end
9
+
10
+ def show
11
+ [
12
+ Elements::Heading.new(text: title),
13
+ Elements::Heading.new(text: subtitle, scale: 0.9),
14
+ Elements::Paragraph.new(text: description)
15
+ ] + [ library_items ]
16
+ end
17
+
18
+ def library_items
19
+ if items
20
+ if show_table
21
+ PeriodicTable.new(elements: items)
22
+ else # items
23
+ items.map do |name:, description:, item_class_name:, item_data:, kind:, color:|
24
+ PeriodicTableEntry.new(
25
+ element_name: name,
26
+ color: color,
27
+ kind: kind)
28
+ end
29
+ end
30
+ elsif item
31
+ LibraryItemExample.new(item)
32
+ else
33
+ []
34
+ end
35
+ end
36
+
37
+ def padding
38
+ @padding ||= 40
39
+ end
40
+
41
+ def background_color
42
+ if color
43
+ Palette.decode_color(color).lighten
44
+ elsif item && item[:color]
45
+ Palette.decode_color(item[:color])
46
+ end
47
+ end
48
+
49
+ def self.description
50
+ "An entry in a library"
51
+ end
52
+
53
+ def self.example_data
54
+ {
55
+ title: "Welcome",
56
+ subtitle: "world",
57
+ description: "Welcome to this section",
58
+ color: "darkblue",
59
+ items: [ LibraryItemExample.example_data ]
60
+ }
61
+ end
62
+ end
63
+ end
64
+ end