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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +11 -0
- data/data/sample_graph.csv +11 -0
- data/lib/wads/app.rb +40 -332
- data/lib/wads/data_structures.rb +236 -19
- data/lib/wads/textinput.rb +20 -14
- data/lib/wads/version.rb +1 -1
- data/lib/wads/widgets.rb +2142 -212
- data/lib/wads.rb +1 -1
- data/media/CircleAlpha.png +0 -0
- data/media/CircleAqua.png +0 -0
- data/media/CircleBlue.png +0 -0
- data/media/CircleGray.png +0 -0
- data/media/CircleGreen.png +0 -0
- data/media/CirclePurple.png +0 -0
- data/media/CircleRed.png +0 -0
- data/media/CircleWhite.png +0 -0
- data/media/CircleYellow.png +0 -0
- data/media/SampleGraph.png +0 -0
- data/media/WadsScreenshot.png +0 -0
- data/run-graph +3 -0
- data/run-star-wars +3 -0
- data/run-stocks +3 -0
- data/run-theme-test +3 -0
- data/samples/basic_gosu_with_graph_widget.rb +66 -0
- data/samples/graph.rb +72 -0
- data/samples/star_wars.rb +112 -0
- data/samples/stocks.rb +126 -0
- data/samples/theme_test.rb +256 -0
- metadata +22 -5
- data/run-sample-app +0 -3
- data/sample_app.rb +0 -64
data/lib/wads.rb
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/media/CircleRed.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/media/SampleGraph.png
CHANGED
Binary file
|
data/media/WadsScreenshot.png
CHANGED
Binary file
|
data/run-graph
ADDED
data/run-star-wars
ADDED
data/run-stocks
ADDED
data/run-theme-test
ADDED
@@ -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
|