wads 0.1.3 → 0.2.0

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.
data/lib/wads.rb CHANGED
@@ -4,4 +4,4 @@ require_relative "wads/version"
4
4
  require_relative "wads/data_structures"
5
5
  require_relative "wads/widgets"
6
6
  require_relative "wads/textinput"
7
-
7
+ require_relative "wads/app"
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
data/run-graph ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/graph.rb
data/run-star-wars ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/star_wars.rb
data/run-stocks ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/stocks.rb
data/run-theme-test ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ruby samples/theme_test.rb $1 $2 $3
@@ -0,0 +1,66 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+ #
6
+ # The WadsApp class provides a simple starting point to quickly build a native
7
+ # Ruby application using Gosu as an underlying library. It provides all the necessary
8
+ # hooks to get started. All you need to do is supply the parent Wads widget using
9
+ # the set_display(widget) method. See one of the Wads samples for example usage.
10
+ #
11
+ class BasicGosuAppWithGraph < Gosu::Window
12
+ def initialize
13
+ super(800, 600)
14
+ self.caption = 'Basic Gosu App with Graph Widget'
15
+ @font = Gosu::Font.new(22)
16
+ @graph_widget = GraphWidget.new(10, 110, # x, y coordinate of top left corder
17
+ 780, 480, # width x height
18
+ create_graph,
19
+ GRAPH_DISPLAY_EXPLORER)
20
+ @update_count = 0
21
+ end
22
+
23
+ def create_graph
24
+ g = Graph.new
25
+ g.add("A")
26
+ g.add("B")
27
+ g.add("C")
28
+ g.add("D")
29
+ g.add("E")
30
+ g.add("F")
31
+ g.connect("A", "B")
32
+ g.connect("A", "C")
33
+ g.connect("B", "D")
34
+ g.connect("B", "E")
35
+ g.connect("E", "F")
36
+ g
37
+ end
38
+
39
+ def update
40
+ # Calling handle_update on the grpah widget is required if you want interactivity
41
+ # specifically, for drag and drop of the nodes
42
+ @update_count = @update_count + 1
43
+ @graph_widget.handle_update @update_count, mouse_x, mouse_y
44
+ end
45
+
46
+ def draw
47
+ @font.draw_text("Sample App with Wads Graph Widget", 240, 49, 1, 1, 1, COLOR_WHITE)
48
+ @graph_widget.draw
49
+ end
50
+
51
+ def button_down id
52
+ close if id == Gosu::KbEscape
53
+ # Delegate button events to the graph widget if you want the
54
+ # user to be able to interact with it
55
+ @graph_widget.button_down id, mouse_x, mouse_y
56
+ end
57
+
58
+ def button_up id
59
+ # Delegate button events to the graph widget if you want the
60
+ # user to be able to interact with it
61
+ @graph_widget.button_up id, mouse_x, mouse_y
62
+ end
63
+ end
64
+
65
+
66
+ BasicGosuAppWithGraph.new.show
data/samples/graph.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+
6
+ class SampleGraphApp < WadsApp
7
+
8
+ SAMPLE_GRAPH_DEFINITION_FILE = "./data/sample_graph.csv"
9
+
10
+ def initialize
11
+ super(800, 600, "Wads Sample Graph App", GraphDisplay.new(create_sample_graph))
12
+ end
13
+
14
+ #
15
+ # Below are three different ways you can construct a graph
16
+ #
17
+ def create_sample_graph
18
+ g = Graph.new
19
+ g.add("A")
20
+ g.add("B")
21
+ g.add("C")
22
+ g.add("D")
23
+ g.add("E")
24
+ g.add("F")
25
+ g.connect("A", "B")
26
+ g.connect("A", "C")
27
+ g.connect("B", "D")
28
+ g.connect("B", "E")
29
+ g.connect("E", "F")
30
+ g
31
+ end
32
+
33
+ def create_sample_graph_using_nodes
34
+ root = Node.new("A")
35
+ b = root.add("B")
36
+ b.add("D")
37
+ b.add("E").add("F")
38
+ root.add("C")
39
+ Graph.new(root)
40
+ end
41
+
42
+ def create_sample_graph_from_file
43
+ Graph.new(SAMPLE_GRAPH_DEFINITION_FILE)
44
+ end
45
+ end
46
+
47
+ class GraphDisplay < Widget
48
+
49
+ def initialize(graph)
50
+ super(0, 0, 800, 600)
51
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
52
+ @graph = graph
53
+
54
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
55
+ image.add_text("Wads Sample App", 10, 20, nil, true)
56
+ image.add_text("Version #{Wads::VERSION}", 13, 54)
57
+
58
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
59
+ panel.add_button("Exit", 0, panel.height - 30) do
60
+ WidgetResult.new(true)
61
+ end
62
+ panel.center_children
63
+ panel.disable_border
64
+
65
+ @graph_display = get_layout.add_graph_display(@graph, GRAPH_DISPLAY_EXPLORER,
66
+ { ARG_SECTION => SECTION_CENTER})
67
+ disable_border
68
+ end
69
+ end
70
+
71
+ #WadsConfig.instance.set_current_theme(WadsNoIconTheme.new)
72
+ SampleGraphApp.new.show
@@ -0,0 +1,112 @@
1
+ require 'gosu'
2
+ require 'json'
3
+ require_relative '../lib/wads'
4
+
5
+ include Wads
6
+
7
+ class SampleStarWarsApp < WadsApp
8
+
9
+ STAR_WARS_DATA_FILE = "./data/starwars-episode-4-interactions.json"
10
+
11
+ def initialize
12
+ super(800, 800, "Wads Sample Star Wars App", StarWarsDisplay.new(process_star_wars_data))
13
+ end
14
+
15
+ def process_star_wars_data
16
+ star_wars_json = File.read(STAR_WARS_DATA_FILE)
17
+ data_hash = JSON.parse(star_wars_json)
18
+ characters = data_hash['nodes']
19
+ interactions = data_hash['links']
20
+
21
+ # The interactions in the data set reference the characters by their
22
+ # zero based index, so we keep a reference in our graph by index.
23
+ # The character's value is the number of scenes in which they appear.
24
+ graph = Graph.new
25
+ characters.each do |character|
26
+ node_tags = {}
27
+ node_color_str = character['colour']
28
+ # This is a bit of a hack, but our background is black so black text
29
+ # will not show up. Change this to white
30
+ if node_color_str == "#000000"
31
+ node_color_str = "#FFFFFF"
32
+ end
33
+ # Convert hex string (ex. "#EE00AA") into int hex representation
34
+ # understood by Gosu color (ex. 0xFFEE00AA)
35
+ node_color = "0xFF#{node_color_str[1..-1]}".to_i(16)
36
+ node_tags['color'] = node_color
37
+ graph.add_node(Node.new(character['name'], character['value'], node_tags))
38
+ end
39
+ interactions.each do |interaction|
40
+ character_one = graph.node_by_index(interaction['source'])
41
+ character_two = graph.node_by_index(interaction['target'])
42
+ number_of_scenes_together = interaction['value']
43
+ edge_tags = {}
44
+ edge_tags["scenes"] = number_of_scenes_together
45
+ graph.add_edge(character_one, character_two, edge_tags)
46
+ end
47
+ graph
48
+ end
49
+ end
50
+
51
+ class StarWarsDisplay < Widget
52
+ attr_accessor :graph
53
+
54
+ def initialize(graph)
55
+ super(0, 0, 800, 800)
56
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
57
+ @graph = graph
58
+
59
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
60
+ image.add_text("Wads Sample App", 10, 20, nil, true)
61
+ image.add_text("Version #{Wads::VERSION}", 13, 54)
62
+
63
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_CENTER})
64
+
65
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
66
+ panel.add_button("Exit", 0, panel.height - 30) do
67
+ WidgetResult.new(true)
68
+ end
69
+ panel.center_children
70
+ panel.disable_border
71
+
72
+ @data_table = get_layout.add_single_select_table(
73
+ ["Character", "Number of Scenes"], 4, { ARG_SECTION => SECTION_CENTER})
74
+
75
+ @graph.node_list.each do |character|
76
+ @data_table.add_row([character.name, character.value], character.get_tag(ARG_COLOR))
77
+ end
78
+ @graph_display = get_layout.add_graph_display(@graph, GRAPH_DISPLAY_EXPLORER,
79
+ { ARG_SECTION => SECTION_CENTER})
80
+
81
+ disable_border
82
+ end
83
+
84
+ def sample_content
85
+ <<~HEREDOC
86
+ This sample analysis shows the interactions between characters in the Star Wars
87
+ Episode 4: A New Hope. Click on a character to see more detail.
88
+ HEREDOC
89
+ end
90
+
91
+ def handle_key_press id, mouse_x, mouse_y
92
+ if id == Gosu::KbUp
93
+ @data_table.scroll_up
94
+ elsif id == Gosu::KbDown
95
+ @data_table.scroll_down
96
+ end
97
+ WidgetResult.new(false)
98
+ end
99
+
100
+ def handle_mouse_down mouse_x, mouse_y
101
+ if @data_table.contains_click(mouse_x, mouse_y)
102
+ val = @data_table.set_selected_row(mouse_y, 0)
103
+ if not val.nil?
104
+ node = @graph.find_node(val)
105
+ #@graph_display.set_center_node(node, 2)
106
+ @graph_display.set_explorer_display(node)
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ SampleStarWarsApp.new.show
data/samples/stocks.rb ADDED
@@ -0,0 +1,126 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+
6
+ class SampleStocksApp < WadsApp
7
+
8
+ STOCKS_DATA_FILE = "./data/NASDAQ.csv"
9
+
10
+ def initialize
11
+ super(800, 600, "Wads Sample Stocks App", StocksDisplay.new(process_stock_data))
12
+ end
13
+
14
+ def process_stock_data
15
+ # The data file comes from https://finance.yahoo.com
16
+ # The format of this file is as follows:
17
+ #
18
+ # Date,Open,High,Low,Close,Adj Close,Volume
19
+ # 2000-01-03,4186.189941,4192.189941,3989.709961,4131.149902,4131.149902,1510070000
20
+ # 2000-01-04,4020.000000,4073.250000,3898.229980,3901.689941,3901.689941,1511840000
21
+ # ...
22
+ # 2020-12-30,12906.509766,12924.929688,12857.759766,12870.000000,12870.000000,5292210000
23
+ # 2020-12-31,12877.089844,12902.070313,12821.230469,12888.280273,12888.280273,4771390000
24
+
25
+ stats = Stats.new("NASDAQ")
26
+ previous_close = nil
27
+
28
+ puts "Read the data file #{STOCKS_DATA_FILE}"
29
+ File.readlines(STOCKS_DATA_FILE).each do |line|
30
+ line = line.chomp # remove the carriage return
31
+
32
+ # Ignore header and any empty lines, process numeric data lines
33
+ if line.length > 0 and line[0].match(/[0-9]/)
34
+ values = line.split(",")
35
+ date = Date.strptime(values[0], "%Y-%m-%d")
36
+ weekday = Date::DAYNAMES[date.wday]
37
+
38
+ open_value = values[1].to_f
39
+ close_value = values[4].to_f
40
+
41
+ if previous_close.nil?
42
+ # Just use the first day to set the baseline
43
+ previous_close = close_value
44
+ else
45
+ change_from_previous_close = close_value - previous_close
46
+ change_intraday = close_value - open_value
47
+ change_overnight = open_value - previous_close
48
+
49
+ change_percent = change_from_previous_close / previous_close
50
+
51
+ stats.add(weekday, change_percent)
52
+ stats.add("#{weekday} prev close", change_from_previous_close)
53
+ stats.add("#{weekday} intraday", change_intraday)
54
+ stats.add("#{weekday} overnight", change_overnight)
55
+
56
+ previous_close = close_value
57
+ end
58
+ end
59
+ end
60
+
61
+ stats
62
+ end
63
+ end
64
+
65
+ class StocksDisplay < Widget
66
+
67
+ def initialize(stats)
68
+ super(0, 0, 800, 600)
69
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
70
+
71
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
72
+ image.add_text("Wads Sample App", 10, 20, nil, true)
73
+ image.add_text("Version #{Wads::VERSION}", 13, 54)
74
+
75
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_CENTER})
76
+
77
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
78
+ panel.add_button("Exit", 0, panel.height - 30) do
79
+ WidgetResult.new(true)
80
+ end
81
+ panel.center_children
82
+
83
+ @data_table = get_layout.add_single_select_table(
84
+ ["Day", "Min", "Avg", "StdDev", "Max", "p10", "p90"], 5,
85
+ { ARG_SECTION => SECTION_CENTER})
86
+ Date::DAYNAMES[1..5].each do |day|
87
+ min = format_percent(stats.min(day))
88
+ avg = format_percent(stats.average(day))
89
+ std = format_percent(stats.std_dev(day))
90
+ max = format_percent(stats.max(day))
91
+ p10 = format_percent(stats.percentile(day, 0.1))
92
+ p90 = format_percent(stats.percentile(day, 0.90))
93
+ @data_table.add_row([day, min, avg, std, max, p10, p90])
94
+ end
95
+
96
+ @selection_text = nil
97
+ end
98
+
99
+ def format_percent(val)
100
+ "#{(val * 100).round(3)}%"
101
+ end
102
+
103
+ def sample_content
104
+ <<~HEREDOC
105
+ This sample stock analysis uses NASDAQ data from https://finance.yahoo.com looking
106
+ at closing data through the years 2000 to 2020. The percent gain or loss is broken
107
+ down per day, as shown in the table below.
108
+ HEREDOC
109
+ end
110
+
111
+ def render
112
+ @selection_text.draw unless @selection_text.nil?
113
+ end
114
+
115
+ def handle_mouse_down mouse_x, mouse_y
116
+ if @data_table.contains_click(mouse_x, mouse_y)
117
+ val = @data_table.set_selected_row(mouse_y, 0)
118
+ if not val.nil?
119
+ @selection_text = Text.new(relative_x(5), relative_y(500), "You selected #{val}, a great day!")
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ WadsConfig.instance.set_current_theme(WadsBrightTheme.new)
126
+ SampleStocksApp.new.show
@@ -0,0 +1,256 @@
1
+ require 'gosu'
2
+ require_relative '../lib/wads'
3
+
4
+ include Wads
5
+
6
+ class ThemeTestApp < WadsApp
7
+ def initialize
8
+ super(800, 600, "Wads Theme Test App", ThemeTestDisplay.new)
9
+ end
10
+ end
11
+
12
+ class ThemeTestDisplay < Widget
13
+ def initialize
14
+ super(0, 0, 800, 600)
15
+ disable_border
16
+
17
+ if ARGV.length == 0
18
+ render_basic_widgets
19
+ elsif ARGV[0] == "-h" or ARGV[0] == "h" or ARGV[0] == "help"
20
+ puts "Wads Theme Tester"
21
+ puts " "
22
+ display_help
23
+ elsif ARGV[0] == "border"
24
+ render_border_layout
25
+ elsif ARGV[0] == "three"
26
+ render_top_middle_bottom_layout
27
+ elsif ARGV[0] == "header"
28
+ render_header_layout
29
+ elsif ARGV[0] == "footer"
30
+ render_footer_layout
31
+ elsif ARGV[0] == "vertical"
32
+ render_vertical_layout
33
+ elsif ARGV[0] == "horizontal"
34
+ render_horizontal_layout
35
+ elsif ARGV[0] == "eastwest"
36
+ render_east_west_layout
37
+ elsif ARGV[0] == "plot"
38
+ render_plot
39
+ elsif ARGV[0] == "form"
40
+ render_form
41
+ elsif ARGV[0] == "overlay"
42
+ render_overlay
43
+ else
44
+ puts "Argument #{ARGV[0]} is invalid."
45
+ display_help
46
+ end
47
+ end
48
+
49
+ def display_help
50
+ puts "Valid arguments are:"
51
+ puts " border show BorderLayout"
52
+ puts " three show TopMiddleBottomLayout"
53
+ puts " header show HeaderContentLayout"
54
+ puts " footer show ContentFooterLayout"
55
+ puts " vertical show VerticalColumnLayout"
56
+ puts " eastwest show EastWestLayout"
57
+ puts " plot show a simple plot using HeaderContentLayout"
58
+ puts " form test a form"
59
+ puts " overlay show an overlay widget"
60
+ exit
61
+ end
62
+
63
+ def render_basic_widgets
64
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
65
+
66
+ # Example of using the layout for absolute positioning
67
+ # and then relative positioning of a child widget
68
+ # within that
69
+ image = get_layout.add_image("./media/Banner.png", { ARG_SECTION => SECTION_TOP})
70
+ image.add_text("Banner", 10, 10)
71
+
72
+ get_layout.add_text("Hello", { ARG_SECTION => SECTION_CENTER})
73
+ get_layout.add_text("There", { ARG_SECTION => SECTION_CENTER})
74
+ get_layout.add_button("Test Button", { ARG_SECTION => SECTION_CENTER}) do
75
+ puts "User hit the test button"
76
+ end
77
+
78
+ table = get_layout.add_multi_select_table(["A", "B", "C"], 4, { ARG_SECTION => SECTION_CENTER})
79
+ table.add_row(["These", "are", "values in row 1"])
80
+ table.add_row(["These", "are", "values in row 2"])
81
+ table.add_row(["These", "are", "values in row 3"])
82
+ table.add_row(["These", "are", "values in row 4"])
83
+
84
+ panel = get_layout.add_horizontal_panel({ ARG_SECTION => SECTION_BOTTOM})
85
+ panel.add_button("Exit", 380, panel.height - 30) do
86
+ WidgetResult.new(true)
87
+ end
88
+ end
89
+
90
+ def render_header_layout
91
+ set_layout(LAYOUT_HEADER_CONTENT)
92
+
93
+ header = get_layout.add_max_panel({ ARG_SECTION => SECTION_HEADER,
94
+ ARG_THEME => WadsNatureTheme.new })
95
+ header.get_layout.add_text("I am the header section",
96
+ { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER,
97
+ ARG_USE_LARGE_FONT => true})
98
+
99
+ main = get_layout.add_max_panel({ ARG_SECTION => SECTION_CONTENT,
100
+ ARG_THEME => WadsNatureTheme.new })
101
+ main.get_layout.add_document(sample_content)
102
+ table = main.get_layout.add_multi_select_table(["A", "B", "C"], 4, { ARG_SECTION => SECTION_WEST})
103
+ table.add_row(["Key1", "Value1", "ValueD"])
104
+ table.add_row(["Key2", "Value2", "ValueE"])
105
+ table.add_row(["Key3", "Value3", "ValueF"])
106
+ end
107
+
108
+ def render_border_layout
109
+ set_layout(LAYOUT_BORDER)
110
+ header = get_layout.add_max_panel({ ARG_SECTION => SECTION_NORTH})
111
+ header.get_layout.add_text("I am the header section", { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER})
112
+
113
+ west = get_layout.add_vertical_panel({ ARG_SECTION => SECTION_WEST})
114
+ west.get_layout.add_button("Do stuff") do
115
+ puts "Hit the do stuff button"
116
+ end
117
+ west.get_layout.add_button("More stuff") do
118
+ puts "Hit the more stuff button"
119
+ end
120
+
121
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_CENTER})
122
+
123
+ east = get_layout.add_vertical_panel({ ARG_SECTION => SECTION_EAST})
124
+ east.get_layout.add_text("item1")
125
+ east.get_layout.add_text("item2")
126
+
127
+ footer = get_layout.add_max_panel({ ARG_SECTION => SECTION_SOUTH})
128
+ footer.get_layout.add_text("I am the footer section", { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER})
129
+ end
130
+
131
+ def render_top_middle_bottom_layout
132
+ set_layout(LAYOUT_TOP_MIDDLE_BOTTOM)
133
+ header = get_layout.add_max_panel({ ARG_SECTION => SECTION_TOP})
134
+ header.get_layout.add_text("I am the header section", { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER})
135
+
136
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_MIDDLE})
137
+
138
+ footer = get_layout.add_max_panel({ ARG_SECTION => SECTION_BOTTOM})
139
+ footer.get_layout.add_text("I am the footer section", { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER})
140
+ end
141
+
142
+ def sample_content
143
+ <<~HEREDOC
144
+ This is the content section.
145
+ A document can contain multi-line text.
146
+ Typically you provide the content
147
+ using a squiggly heredoc.
148
+ HEREDOC
149
+ end
150
+
151
+ def render_footer_layout
152
+ set_layout(LAYOUT_CONTENT_FOOTER)
153
+
154
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_CONTENT})
155
+
156
+ footer = get_layout.add_max_panel({ ARG_SECTION => SECTION_FOOTER,
157
+ ARG_THEME => WadsBrightTheme.new })
158
+ footer.get_layout.add_text("I am the footer section", { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER})
159
+ end
160
+
161
+ def render_vertical_layout
162
+ set_layout(LAYOUT_VERTICAL_COLUMN)
163
+ get_layout.add_image("./media/Banner.png")
164
+ get_layout.add_text("This is text below the image")
165
+ get_layout.add_text("Each widget will get placed below the previous in a vertical column.")
166
+ end
167
+
168
+ def render_east_west_layout
169
+ set_layout(LAYOUT_EAST_WEST)
170
+ table = get_layout.add_multi_select_table(["A", "B", ""], 4, { ARG_SECTION => SECTION_WEST})
171
+ table.add_row(["Key1", "Value1"])
172
+ table.add_row(["Key2", "Value2"])
173
+ table.add_row(["Key3", "Value3"])
174
+
175
+ get_layout.add_document(sample_content, { ARG_SECTION => SECTION_EAST})
176
+ end
177
+
178
+ def render_plot
179
+ set_layout(LAYOUT_HEADER_CONTENT)
180
+
181
+ header = get_layout.add_max_panel({ ARG_SECTION => SECTION_HEADER,
182
+ ARG_THEME => WadsBrightTheme.new })
183
+ # The zero x coord doesn't matter here because we center it below
184
+ # Centering only adjusts the x coordinate
185
+ header.add_text("This is a plot of sine (yellow) and cosine (pink) waves", 0, 35)
186
+ header.center_children
187
+ header.disable_border
188
+
189
+ plot = get_layout.add_plot({ ARG_SECTION => SECTION_CONTENT})
190
+ plot.define_range(VisibleRange.new(-5, 5, -5, 5))
191
+ plot.enable_border
192
+ x = -5
193
+ while x < 5
194
+ plot.add_data_point("Sine", x, Math.sin(x), COLOR_LIME)
195
+ plot.add_data_point("Cosine", x, Math.cos(x), COLOR_PINK)
196
+ x = x + 0.05
197
+ end
198
+
199
+ # Draw the 0 horizontal and vertical axes
200
+ plot.add_child(Line.new(plot.draw_x(0), plot.draw_y(-5), plot.draw_x(0), plot.draw_y(5), COLOR_GRAY))
201
+ plot.add_child(Line.new(plot.draw_x(-5), plot.draw_y(0), plot.draw_x(5), plot.draw_y(0), COLOR_GRAY))
202
+ end
203
+
204
+ def render_form
205
+ set_layout(LAYOUT_CONTENT_FOOTER)
206
+
207
+ content_panel = get_layout.add_max_panel({ ARG_SECTION => SECTION_CONTENT,
208
+ ARG_LAYOUT => LAYOUT_EAST_WEST,
209
+ ARG_PANEL_WIDTH => 200 })
210
+
211
+ label_panel = content_panel.add_panel(SECTION_WEST)
212
+ label_panel.get_layout.add_text("First Name", { ARG_TEXT_ALIGN => TEXT_ALIGN_RIGHT})
213
+ label_panel.get_layout.add_text("Middle Name", { ARG_TEXT_ALIGN => TEXT_ALIGN_RIGHT})
214
+ label_panel.get_layout.add_text("Last Name", { ARG_TEXT_ALIGN => TEXT_ALIGN_RIGHT})
215
+
216
+ field_panel = content_panel.add_panel(SECTION_EAST)
217
+ @first_name = field_panel.get_layout.add_text_input(200)
218
+ @middle_name = field_panel.get_layout.add_text_input(200)
219
+ @last_name = field_panel.get_layout.add_text_input(200)
220
+
221
+ footer_panel = get_layout.add_max_panel({ ARG_SECTION => SECTION_FOOTER})
222
+ footer_panel.get_layout.add_button("Display Full Name", {ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER}) do
223
+ footer_panel.get_layout.add_text("The full name is #{@first_name.text} #{@middle_name.text} #{@last_name.text}.")
224
+ end
225
+ end
226
+
227
+ def render_overlay
228
+ set_layout(LAYOUT_HEADER_CONTENT)
229
+
230
+ header = get_layout.add_max_panel({ ARG_SECTION => SECTION_HEADER})
231
+ header.get_layout.add_text("I am the header section", { ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER})
232
+
233
+ main = get_layout.add_max_panel({ ARG_SECTION => SECTION_CONTENT})
234
+ main.get_layout.add_document(sample_content)
235
+
236
+ main.get_layout.add_button("Display InfoBox", {ARG_TEXT_ALIGN => TEXT_ALIGN_CENTER}) do
237
+ add_overlay(create_overlay_widget)
238
+ end
239
+ end
240
+
241
+ def create_overlay_widget
242
+ InfoBox.new(100, 60, 600, 400, "Sample Overlay", overlay_content, { ARG_THEME => WadsBrightTheme.new})
243
+ end
244
+
245
+ def overlay_content
246
+ <<~HEREDOC
247
+ This is a sample overlay widget which typically
248
+ you would use to display important information
249
+ upon request. The InfoBox widget is used for
250
+ this purpose.
251
+ HEREDOC
252
+
253
+ end
254
+ end
255
+
256
+ ThemeTestApp.new.show