Professional Documents
Culture Documents
1. Ruby
a) MineOPS
b) JSPanel
c) Painters
d) Icons and images
2. Ruby-Gnome
a) gtk_widgets.rb
b) rb.xml files
c) Common patterns
2 Confidential
Ruby
/opt/Jigsaw/Library…
• jminegraph/app/views
• jminegraph/app/controllers
• jminegraph/app/widgets
• jminegraph/app/widgets/painters
• jmineops
• ruby/models
• ruby/jspanel
4 Confidential
General MineOPS Views
/opt/Jigsaw/Library…
• jminegraph/app/views
• jminegraph/app/controllers
• jminegraph/app/widgets
• jminegraph/app/widgets/painters
• jmineops
• ruby/models
• ruby/jspanel
5 Confidential
MineOPS Mine Map / Playback
/opt/Jigsaw/Library…
• jminegraph/app/views
• jminegraph/app/controllers
• jminegraph/app/widgets
• jminegraph/app/widgets/painters
• jmineops
• ruby/models
• ruby/jspanel
6 Confidential
JSPanel Code Locations
/opt/Jigsaw/Library…
• jminegraph/app/views
• jminegraph/app/controllers
• jminegraph/app/widgets
• jminegraph/app/widgets/painters
• jmineops
• ruby/models
• ruby/jspanel
7 Confidential
Database Code Locations
/opt/Jigsaw/Library…
•
•
jminegraph/app/views
jminegraph/app/controllers
Migration scripts
• jminegraph/app/widgets SQL stored procedures
• jminegraph/app/widgets/painters
• jmineops Database views
• ruby/models
• ruby/jspanel
8 Confidential
Ruby
/opt/Jigsaw/Library…
• jminegraph/app/views
• jminegraph/app/controllers
• jminegraph/app/widgets
• jminegraph/app/widgets/painters
• jmineops
• ruby/models
• ruby/jspanel
10 Confidential
General MineOPS Views
TruckView
EquipmentView
EditorView
UtilityView
View
11 Confidential
General MineOPS Views
TruckView
EquipmentView
EditorView
UtilityView
View
12 Confidential
Table Tab
General MineOPS Views Detail Tab
TruckView
EquipmentView
EditorView
UtilityView
View
13 Confidential
General MineOPS Views
14 Confidential
General MineOPS Views
View: view is based on the truck_view Class
Class Name: view will show Truck objects (data)
Truck/Equipment-specific
settings (mostly)
15 Confidential
General MineOPS Views
16 Confidential
General MineOPS Views
17 Confidential
Gnome UI Widgets (gtk_widgets)
Generally applies to both MineOPS and JSPanel…
The points of difference are:
• Source locations:
• Library/jminegraph/app/widgets/gtk_widgets.rb (MineOPS)
• Library/ruby/jspanel/gtk_widgets.rb (JSPanel)
• MineOPS is plain Ruby code
• JSPanel is mostly rb.xml
• MineOPS uses the display_selectors table
18 Confidential
Gnome UI Widgets (gtk_widgets)
We don’t directly instantiate Gnome/GTK objects.
We create instances from the classes defined in the gtk_widgets.rb files
19 Confidential
Ruby
Rb.xml files are XML-based tags that are used to help layout the widgets
within the panel.
Some logic is defined in these files, but generally, we prefer to keep logic
in Objective-C rather than rb.xml.
• Objective-C is much faster
• We’d like to get rid of Ruby/Gnome UI at some stage in the future
21 Confidential
JSPanel & rb.xml files
The generated Ruby outputs are cached so that subsequent panel startup
times are accelerated (Library/ruby/jspanel/cache).
22 Confidential
JSPanel & rb.xml files
The generated Ruby outputs are cached so that subsequent panel startup
times are accelerated (Library/ruby/jspanel/cache).
23 Confidential
JSPanel layout (rb.xml)
<frame name="w0" font_size="20" undecorated="true" visible="true“
location="0,0" maximized="true" size="1024,768">
<menubar name="mn" size="160,92">
<menu name="jigsaw" image="puzzle_82x82.png" label="" size="10,92">
<include name="system_menu"/>
<include name="truck_activity_menu" not_config="disable_truck_activity_menu"/>
<include name="truck_status_menu"/>
<include name="operations_menu"/>
<include name="road_conditions_menu" config="road_condition_enabled” />
<include name="message_menu"/>
<include name="truck_help_menu" not_config="disable_truck_help_menu"/>
<include name="emergency_menu"/>
</menu>
w0 (Frame)
w0.mn (Menubar)
w0.mn.jigsaw (Menu)
24 Confidential
JSPanel layout (rb.xml)
<frame name="w0" font_size="20" undecorated="true" visible="true“
location="0,0" maximized="true" size="1024,768">
<menubar name="mn" size="160,92">
<menu name="jigsaw" image="puzzle_82x82.png" label="" size="10,92">
<include name="system_menu"/>
<include name="truck_activity_menu" not_config="disable_truck_activity_menu
<include name="truck_status_menu"/>
<include name="operations_menu"/>
<include name="road_conditions_menu" config="road_condition_enabled” />
<include name="message_menu"/>
<include name="truck_help_menu" not_config="disable_truck_help_menu"/>
<include name="emergency_menu"/>
</menu>
25 Confidential
JSPanel layout (rb.xml)
<frame name="w0" font_size="20" undecorated="true" visible="true“
location="0,0" maximized="true" size="1024,768">
<menubar name="mn" size="160,92">
<menu name="jigsaw" image="puzzle_82x82.png" label="" size="10,92">
<include name="system_menu"/>
<include name="truck_activity_menu" not_config="disable_truck_activity_menu"/>
<include name="truck_status_menu"/>
<include name="operations_menu"/>
<include name="road_conditions_menu" config="road_condition_enabled” />
<include name="message_menu"/>
<include name="truck_help_menu" not_config="disable_truck_help_menu"/>
<include name="emergency_menu"/>
</menu>
26 Confidential
JSPanel layout (rb.xml)
<frame name="w0" font_size="20" undecorated="true" visible="true“
location="0,0" maximized="true" size="1024,768">
<menubar name="mn" size="160,92">
<menu name="jigsaw" image="puzzle_82x82.png" label="" size="10,92">
<include name="system_menu"/>
<include name="truck_activity_menu" not_config="disable_truck_activity_menu"/>
<include name="truck_status_menu"/>
<include name="operations_menu"/>
<include name="road_conditions_menu" config="road_condition_enabled” />
<include name="message_menu"/>
<include name="truck_help_menu" not_config="disable_truck_help_menu"/>
<include name="emergency_menu"/>
</menu>
27 Confidential
JSPanel layout (truck_status_menu.rb.xml)
<menu name="status" display_label="STATUS" size="230,70">
<menuitem display_label="READY" image="truck_ready_82x82.png" size="220,70" background="green" change_colors="false">
status_selection "ready"
</menuitem>
<menuitem display_label="DOWN" image="truck_down_82x82.png" size="220,70" background="red" change_colors="false">
status_selection "down"
</menuitem>
<menuitem display_label="DELAY" image="truck_delay_82x82.png" size="220,70" background="orange" change_colors="false">
status_selection "delay"
</menuitem>
<menuitem display_label="STANDBY" image="truck_spare_82x82.png“
size="220,70" background="blue" change_colors="false">
status_selection "standby"
</menuitem>
<menuitem display_label="SHIFT CHANGE“
size="220,70" change_colors="false" config="enable_shift_change_status">
status_selection "shift_change"
</menuitem>
</menu>
28 Confidential
JSPanel layout (truck_status_menu.rb.xml)
29 Confidential
JSPanel layout (truck_status_menu.rb.xml)
<menuitem display_label="READY" image="truck_ready_82x82.png" size="220,70" background="green" change_colors="false">
status_selection "ready"
</menuitem>
def foreground=(color)
super
if @sensitive.nil? || @sensitive
c = get_color(color)
else
c = get_color("gray")
end
Gtk.post_update do
@gtk_object.child.modify_fg(Gtk::STATE_NORMAL, c) if @gtk_object
@label.modify_fg(Gtk::STATE_NORMAL, c) if @label
end
end
end
30 Confidential
JSPanel layout (truck_status_menu.rb.xml)
<menuitem display_label="READY" image="truck_ready_82x82.png" size="220,70" background="green" change_colors="false">
status_selection "ready"
</menuitem>
31 Confidential
Gtk_widgets: creating UI widgets
class Button < GuiWidget
…
# initialize widget GtkWidgets::Button
def create
@image_size=[82,82]
b = Gtk::Button.new Gtk::Button
b.set_label("")
set_gtk_object(b)
32 Confidential
Gtk_widgets: creating UI widgets
class Button < GuiWidget
…
# initialize widget GtkWidgets::Button
def create These are
@image_size=[82,82] not the same
b = Gtk::Button.new Gtk::Button
b.set_label("")
set_gtk_object(b)
33 Confidential
More examples with buttons - actions
@gtk_object.signal_connect('pressed') do |w,e|
performAction e
end
34 Confidential
More examples with buttons - cloning
35 Confidential
More examples with buttons - cloning
<dialog name="blast_dialog" display_title="" location="0,0" size="1024,768" undecorated="true">
<panel layout="ybox">
<field height="100" display_label="Select your blast zone" font_size="30"/>
<scrollpane height="560" policy="never,auto" vscrollbar_size="60,60">
<panel name="panel" layout="grid 0 3">
<button name="list" source_label="name" font_size="20" width="100">
set_selected_blast active_widget.object
blast_dialog.unpost
</button>
</panel>
</scrollpane>
<button name="cancel" display_label="CANCEL" font_size="24" height="100">
blast_dialog.unpost
</button>
</panel>
</dialog>
36 Confidential
More examples with buttons - cloning
<dialog name="blast_dialog" display_title="" location="0,0" size="1024,768" undecorated="true">
<panel layout="ybox">
<field height="100" display_label="Select your blast zone" font_size="30"/>
<scrollpane height="560" policy="never,auto" vscrollbar_size="60,60">
<panel name="panel" layout="grid 0 3">
<button name="list" source_label="name" font_size="20" width="100">
set_selected_blast active_widget.object
blast_dialog.unpost
</button>
</panel>
</scrollpane>
<button name="cancel" display_label="CANCEL" font_size="24" height="100">
blast_dialog.unpost
</button>
</panel>
</dialog>
37 Confidential
Panels
<dialog name="blast_dialog" display_title="" location="0,0" size="1024,768" undecorated="true">
<panel layout="ybox">
<field height="100" display_label="Select your blast zone" font_size="30"/>
<scrollpane height="560" policy="never,auto" vscrollbar_size="60,60">
<panel name="panel" layout="grid 0 3">
<button name="list" source_label="name" font_size="20" width="100">
set_selected_blast active_widget.object
blast_dialog.unpost
</button>
</panel>
</scrollpane>
<button name="cancel" display_label="CANCEL" font_size="24" height="100">
blast_dialog.unpost
</button>
</panel>
</dialog>
38 Confidential
Panels
<dialog name="kp" title="Keypad">
<panel layout="ybox">
<label name="hint" size="240,40" font_size="20.0"/>
<panel layout="xbox">
<field name="d" size="500,100" font_size="24.0" background="white"/>
</panel>
<panel layout="grid 0 3">
<button label="1" size="100,100" font_size="20.0">kp.d.append("1")</button>
<button label="2" size="100,100" font_size="20.0">kp.d.append("2")</button>
<button label="3" size="100,100" font_size="20.0">kp.d.append("3")</button>
<button label="4" size="100,100" font_size="20.0">kp.d.append("4")</button>
<button label="5" size="100,100" font_size="20.0">kp.d.append("5")</button>
<button label="6" size="100,100" font_size="20.0">kp.d.append("6")</button>
<button label="7" size="100,100" font_size="20.0">kp.d.append("7")</button>
<button label="8" size="100,100" font_size="20.0">kp.d.append("8")</button>
<button label="9" size="100,100" font_size="20.0">kp.d.append("9")</button>
<button label="+/-" size="100,100" font_size="20.0">
if kp.d.text.to_f > 0.0
kp.d.write("-"+kp.d.text)
elsif kp.d.text.to_f < 0.0
kp.d.write(kp.d.text.gsub("-",""))
end
</button>
<button label="0" size="100,100" font_size="20.0">kp.d.append("0")</button>
<button label="." size="100,100" font_size="20.0">kp.d.append(".")</button>
</panel>
<panel layout="xbox" size="240,100">
<button display_label="DEL" font_size="20.0" width="125">kp.d.delete</button>
<button display_label="CLR" font_size="20.0" width="125">kp.d.clear</button>
<button display_label="Cancel" width="125">kp.cancel_and_unpost</button>
<button display_label="OK" font_size="20.0" width="125">kp.doit</button>
</panel>
</panel>
</dialog>
39 Confidential
Panels
<dialog name="kp" title="Keypad">
<panel layout="ybox">
<label name="hint" size="240,40" font_size="20.0"/>
<panel layout="xbox">
<field name="d" size="500,100" font_size="24.0" background="white"/>
</panel>
<panel layout="grid 0 3">
<button label="1" size="100,100" font_size="20.0">kp.d.append("1")</button>
<button label="2" size="100,100" font_size="20.0">kp.d.append("2")</button>
<button label="3" size="100,100" font_size="20.0">kp.d.append("3")</button>
<button label="4" size="100,100" font_size="20.0">kp.d.append("4")</button>
<button label="5" size="100,100" font_size="20.0">kp.d.append("5")</button>
<button label="6" size="100,100" font_size="20.0">kp.d.append("6")</button>
<button label="7" size="100,100" font_size="20.0">kp.d.append("7")</button>
<button label="8" size="100,100" font_size="20.0">kp.d.append("8")</button>
<button label="9" size="100,100" font_size="20.0">kp.d.append("9")</button>
<button label="+/-" size="100,100" font_size="20.0">
if kp.d.text.to_f > 0.0
kp.d.write("-"+kp.d.text)
elsif kp.d.text.to_f < 0.0
kp.d.write(kp.d.text.gsub("-",""))
end
</button>
<button label="0" size="100,100" font_size="20.0">kp.d.append("0")</button>
<button label="." size="100,100" font_size="20.0">kp.d.append(".")</button>
</panel>
<panel layout="xbox" size="240,100">
<button display_label="DEL" font_size="20.0" width="125">kp.d.delete</button>
<button display_label="CLR" font_size="20.0" width="125">kp.d.clear</button>
<button display_label="Cancel" width="125">kp.cancel_and_unpost</button>
<button display_label="OK" font_size="20.0" width="125">kp.doit</button>
</panel>
</panel>
</dialog>
40 Confidential
Panels
<dialog name="kp" title="Keypad">
<panel layout="ybox"> hint
<label name="hint" size="240,40" font_size="20.0"/>
<panel layout="xbox"> d
<field name="d" size="500,100" font_size="24.0" background="white"/>
</panel>
<panel layout="grid 0 3">
<button label="1" size="100,100" font_size="20.0">kp.d.append("1")</button> grid
<button label="2" size="100,100" font_size="20.0">kp.d.append("2")</button>
<button label="3" size="100,100" font_size="20.0">kp.d.append("3")</button>
<button label="4" size="100,100" font_size="20.0">kp.d.append("4")</button>
<button label="5" size="100,100" font_size="20.0">kp.d.append("5")</button>
<button label="6" size="100,100" font_size="20.0">kp.d.append("6")</button>
<button label="7" size="100,100" font_size="20.0">kp.d.append("7")</button>
<button label="8" size="100,100" font_size="20.0">kp.d.append("8")</button>
<button label="9" size="100,100" font_size="20.0">kp.d.append("9")</button>
<button label="+/-" size="100,100" font_size="20.0">
if kp.d.text.to_f > 0.0
kp.d.write("-"+kp.d.text)
elsif kp.d.text.to_f < 0.0
kp.d.write(kp.d.text.gsub("-",""))
end
</button>
<button label="0" size="100,100" font_size="20.0">kp.d.append("0")</button>
<button label="." size="100,100" font_size="20.0">kp.d.append(".")</button>
</panel>
<panel layout="xbox" size="240,100">
<button display_label="DEL" font_size="20.0" width="125">kp.d.delete</button> xbox
<button display_label="CLR" font_size="20.0" width="125">kp.d.clear</button>
<button display_label="Cancel" width="125">kp.cancel_and_unpost</button>
<button display_label="OK" font_size="20.0" width="125">kp.doit</button>
</panel>
</panel>
</dialog>
41 Confidential
Macros, Symbols, Timers
<symbol name="panel_color_scheme"/>
<symbol name="system_background_colour"/>
<symbol name="system_foreground_colour"/>
<macro name="day">
bground = config(:day_background) || @default_bg_color || "white"
fground = config(:day_foreground) || "black"
Symbols are like self.backgrounds = bground
global variables self.foregrounds = fground
system_background_colour.value = bground
system_foreground_colour.value = fground
panel_color_scheme.value = :day
</macro>
<macro name="night">
bground = config(:night_background) || "#282828"
fground = config(:night_foreground) || "white"
system_background_colour.value = bground
system_foreground_colour.value = fground
self.backgrounds = bground
self.foregrounds = fground
panel_color_scheme.value = :night
</macro>
42 Confidential
Macros, Symbols, Timers
<timer name="time_display" timeout="1000">
begin
if self.respond_to?(:date_widget) && self.date_widget.respond_to?(:label=)
self.date_widget.label=Time.now.strftime("%H:%M:%S")
end
rescue Exception => e
$stderr.puts "Time update failed : #{e}"
end
true
</timer>
# elsewhere...
timer_display.start
43 Confidential
Macros, Symbols, Timers
<timer name="time_display" timeout="1000">
begin
if self.respond_to?(:date_widget) && self.date_widget.respond_to?(:label=)
self.date_widget.label=Time.now.strftime("%H:%M:%S")
end
rescue Exception => e
$stderr.puts "Time update failed : #{e}"
end
true
</timer>
# elsewhere...
timer_display.start
Side Note:
Timers are in a separate Thread
44 Confidential
Macros, Symbols, Timers
<timer name="time_display" timeout="1000">
begin
if self.respond_to?(:date_widget) && self.date_widget.respond_to?(:label=)
self.date_widget.label=Time.now.strftime("%H:%M:%S")
end
rescue Exception => e
$stderr.puts "Time update failed : #{e}"
end
true
</timer>
45 Confidential
Ruby
Painters are used to represent objects in the map (eg. Trucks, Dumps, Roads).
JSPanel and MineOPS share the same painters (codebase).
See: /opt/Jigsaw/Library/jminegraph/app/widgets/painters
Also: /opt/Jigsaw/Images/jminegraph/canvas
47 Confidential
Painters
A painter can have some limited logic to decide how to depict an object for it’s
given state. For example, most equipment painters rely on activity or status.
48 Confidential
Painters – MineOPS Mine Map
In MineOPS, the Mine Map uses LayerViews.
Each selects a mapping between an object
type (eg. Truck) and the most appropriate
painter to use for that object (eg. TruckPainter)
49 Confidential
Painters – MineOPS Mine Map
50 Confidential
Painters – JSPanel Mine Map
51 Confidential
Ruby
Project.jams_notify(:insert){|p| projects_reload}
Project.jams_notify(:update){|p| projects_reload}
Project.jams_notify(:delete){|pid| projects_reload}
53 Confidential
Ruby – Respond to message from JAMS
conn = ActiveRecord::Base.connection
…
conn.listen('guiMessage'){|msg|
if "#{msg}" == "SILENT HORN"
show_silent_horn
else
show_gui_message msg
end
}
54 Confidential
Ruby – irb and ‘jams_connect’
55 Confidential
Exhausted?
56 Confidential