wads 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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