clevic 0.12.0 → 0.13.0.b1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/Manifest.txt +209 -30
- data/README.txt +16 -20
- data/Rakefile +8 -8
- data/TODO +6 -7
- data/bin/clevic +12 -73
- data/lib/clevic/action_builder.rb +168 -0
- data/lib/clevic/ar_methods.rb +120 -0
- data/lib/clevic/attribute_list.rb +56 -0
- data/lib/clevic/cache_table.rb +60 -37
- data/lib/clevic/default_view.rb +3 -16
- data/lib/clevic/delegate.rb +46 -0
- data/lib/clevic/emitter.rb +38 -0
- data/lib/clevic/extensions.rb +61 -114
- data/lib/clevic/field.rb +159 -228
- data/lib/clevic/field_valuer.rb +165 -0
- data/lib/clevic/filter_command.rb +2 -6
- data/lib/clevic/generic_format.rb +52 -0
- data/lib/clevic/{ui → icons}/icon.png +0 -0
- data/lib/clevic/many_field.rb +7 -0
- data/lib/clevic/model_builder.rb +234 -146
- data/lib/clevic/model_column.rb +61 -13
- data/lib/clevic/order_attribute.rb +10 -0
- data/lib/clevic/qt.rb +35 -0
- data/lib/clevic/qt/action_builder.rb +47 -0
- data/lib/clevic/qt/boolean_delegate.rb +8 -0
- data/lib/clevic/{browser.rb → qt/browser.rb} +35 -14
- data/lib/clevic/qt/clipboard.rb +35 -0
- data/lib/clevic/qt/combo_delegate.rb +198 -0
- data/lib/clevic/qt/delegates.rb +1 -0
- data/lib/clevic/qt/distinct_delegate.rb +35 -0
- data/lib/clevic/qt/extensions.rb +52 -0
- data/lib/clevic/qt/field.rb +18 -0
- data/lib/clevic/{item_delegate.rb → qt/item_delegate.rb} +8 -4
- data/lib/clevic/qt/relational_delegate.rb +87 -0
- data/lib/clevic/{search_dialog.rb → qt/search_dialog.rb} +1 -11
- data/lib/clevic/qt/set_delegate.rb +44 -0
- data/lib/clevic/qt/table_model.rb +331 -0
- data/lib/clevic/qt/table_view.rb +344 -0
- data/lib/clevic/qt/text_area_delegate.rb +8 -0
- data/lib/clevic/{text_delegate.rb → qt/text_delegate.rb} +6 -4
- data/lib/clevic/{ui → qt/ui}/.gitignore +0 -0
- data/lib/clevic/{ui → qt/ui}/browser.ui +0 -0
- data/lib/clevic/{ui → qt/ui}/search_dialog.ui +0 -0
- data/lib/clevic/rails_models_loaders.rb +56 -0
- data/lib/clevic/record.rb +2 -17
- data/lib/clevic/sampler.rb +81 -0
- data/lib/clevic/sequel_ar_adapter.rb +215 -0
- data/lib/clevic/sequel_length_validation.rb +23 -0
- data/lib/clevic/sequel_meta.rb +65 -0
- data/lib/clevic/sequel_naked.rb +30 -0
- data/lib/clevic/swing.rb +38 -0
- data/lib/clevic/swing/action.rb +125 -0
- data/lib/clevic/swing/action_builder.rb +47 -0
- data/lib/clevic/swing/boolean_delegate.rb +26 -0
- data/lib/clevic/swing/browser.rb +282 -0
- data/lib/clevic/swing/cell_editor.rb +95 -0
- data/lib/clevic/swing/cell_renderer.rb +44 -0
- data/lib/clevic/swing/clipboard.rb +135 -0
- data/lib/clevic/swing/combo_delegate.rb +336 -0
- data/lib/clevic/swing/confirm_dialog.rb +57 -0
- data/lib/clevic/swing/delegate.rb +40 -0
- data/lib/clevic/swing/distinct_delegate.rb +30 -0
- data/lib/clevic/swing/extensions.rb +274 -0
- data/lib/clevic/swing/field.rb +35 -0
- data/lib/clevic/swing/relational_delegate.rb +48 -0
- data/lib/clevic/swing/row_header.rb +210 -0
- data/lib/clevic/swing/search_dialog.rb +230 -0
- data/lib/clevic/swing/selection_model.rb +90 -0
- data/lib/clevic/swing/set_delegate.rb +41 -0
- data/lib/clevic/swing/swing_table_index.rb +43 -0
- data/lib/clevic/swing/table_model.rb +200 -0
- data/lib/clevic/swing/table_view.rb +385 -0
- data/lib/clevic/swing/table_view_focus.rb +47 -0
- data/lib/clevic/swing/tag_delegate.rb +127 -0
- data/lib/clevic/swing/tag_editor.rb +101 -0
- data/lib/clevic/swing/text_area_delegate.rb +46 -0
- data/lib/clevic/swing/text_delegate.rb +31 -0
- data/lib/clevic/swing/ui/build.xml +74 -0
- data/lib/clevic/swing/ui/dist/README.TXT +33 -0
- data/lib/clevic/swing/ui/dist/lib/swing-layout-1.0.3.jar +0 -0
- data/lib/clevic/swing/ui/manifest.mf +3 -0
- data/lib/clevic/swing/ui/nbproject/build-impl.xml +731 -0
- data/lib/clevic/swing/ui/nbproject/genfiles.properties +8 -0
- data/lib/clevic/swing/ui/nbproject/private/config.properties +0 -0
- data/lib/clevic/swing/ui/nbproject/private/private.properties +6 -0
- data/lib/clevic/swing/ui/nbproject/private/private.xml +4 -0
- data/lib/clevic/swing/ui/nbproject/project.properties +70 -0
- data/lib/clevic/swing/ui/nbproject/project.xml +14 -0
- data/lib/clevic/swing/ui/src/SearchDialog.form +158 -0
- data/lib/clevic/swing/ui/src/SearchDialog.java +163 -0
- data/lib/clevic/swing/ui/src/TagEditor.form +106 -0
- data/lib/clevic/swing/ui/src/TagEditor.java +108 -0
- data/lib/clevic/swing/ui/src/resources/SearchDialog.properties +0 -0
- data/lib/clevic/table_index.rb +100 -0
- data/lib/clevic/table_model.rb +54 -425
- data/lib/clevic/table_searcher.rb +113 -116
- data/lib/clevic/table_view.rb +171 -399
- data/lib/clevic/table_view_paste.rb +199 -0
- data/lib/clevic/version.rb +3 -2
- data/lib/clevic/view.rb +94 -43
- data/models/accounts_models.rb +13 -13
- data/models/minimal_models.rb +5 -9
- data/models/times_models.rb +19 -14
- data/models/times_psql_models.rb +10 -0
- data/models/times_sqlite_models.rb +1 -8
- data/models/values_models.rb +2 -8
- data/tasks/clevic.rake +1 -1
- data/tasks/rdoc.rake +1 -5
- data/tasks/website.rake +1 -1
- data/test/test_cache_table.rb +15 -29
- data/test/test_helper.rb +14 -83
- data/test/test_order_attribute.rb +1 -1
- data/test/test_table_model.rb +0 -21
- data/test/test_table_searcher.rb +67 -61
- metadata +262 -78
- data/lib/clevic.rb +0 -4
- data/lib/clevic/db_options.rb +0 -112
- data/lib/clevic/delegates.rb +0 -386
data/lib/clevic/swing.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
=begin
|
2
|
+
Require this file to do Clevic in Swing with JRuby
|
3
|
+
=end
|
4
|
+
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
# This seems to be required for jruby-1.5.x (at least for 1.5.2)
|
8
|
+
require 'java'
|
9
|
+
|
10
|
+
# require these first, so TableModel and TableView get the correct ancestors
|
11
|
+
require 'clevic/swing/table_model.rb'
|
12
|
+
require 'clevic/swing/table_view.rb'
|
13
|
+
( Pathname.new( __FILE__ ).parent + 'swing' ).children.grep( /.rb$/ ).each do |child|
|
14
|
+
require child.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
# now require the generic parts
|
18
|
+
require 'clevic/table_model'
|
19
|
+
require 'clevic/table_view'
|
20
|
+
require 'clevic.rb'
|
21
|
+
|
22
|
+
module Clevic
|
23
|
+
|
24
|
+
def self.tahoma
|
25
|
+
if @font.nil?
|
26
|
+
@font =
|
27
|
+
begin
|
28
|
+
found = java.awt.GraphicsEnvironment.local_graphics_environment.all_fonts.select {|f| f.font_name == "Tahoma"}.first
|
29
|
+
found.deriveFont( 13.0 )
|
30
|
+
java.awt.Font.new( 'DialogInput', java.awt.Font::PLAIN, 13 )
|
31
|
+
rescue
|
32
|
+
java.awt.Font.new( 'DialogInput', java.awt.Font::PLAIN, 13 )
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@font
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'gather'
|
2
|
+
|
3
|
+
module Clevic
|
4
|
+
|
5
|
+
class Action
|
6
|
+
include Gather
|
7
|
+
property :shortcut, :method, :handler, :tool_tip, :visible, :name, :text, :checkable
|
8
|
+
|
9
|
+
def initialize( parent, options = {}, &block )
|
10
|
+
@parent = parent
|
11
|
+
gather( options, &block )
|
12
|
+
end
|
13
|
+
attr_reader :parent, :menu_item
|
14
|
+
|
15
|
+
def plain_text
|
16
|
+
text.gsub( /&/, '' )
|
17
|
+
end
|
18
|
+
|
19
|
+
# find the java.awt.event.KeyEvent::VK constant
|
20
|
+
# for the letter after the &. Then set it on the item's
|
21
|
+
# mnemonic. Because JMenuItem.setMnemonic won't take a nil
|
22
|
+
def mnemonic
|
23
|
+
if @mnemonic.nil?
|
24
|
+
ix = text.index '&'
|
25
|
+
@mnemonic =
|
26
|
+
if ix
|
27
|
+
eval( "java.awt.event.KeyEvent::VK_#{text[ix+1..ix+1].upcase}" )
|
28
|
+
else
|
29
|
+
false
|
30
|
+
end
|
31
|
+
end
|
32
|
+
@mnemonic
|
33
|
+
end
|
34
|
+
|
35
|
+
def menu_item
|
36
|
+
if @menu_item.nil?
|
37
|
+
@menu_item =
|
38
|
+
if checkable
|
39
|
+
javax.swing.JCheckBoxMenuItem.new
|
40
|
+
else
|
41
|
+
javax.swing.JMenuItem.new
|
42
|
+
end
|
43
|
+
|
44
|
+
menu_item.text = plain_text
|
45
|
+
menu_item.mnemonic = mnemonic if mnemonic
|
46
|
+
menu_item.accelerator = parse_shortcut( shortcut ) unless shortcut.nil?
|
47
|
+
menu_item.tool_tip_text = tool_tip
|
48
|
+
menu_item.add_action_listener do |event|
|
49
|
+
handler.call( event )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@menu_item
|
53
|
+
end
|
54
|
+
|
55
|
+
# parse a Qt-style Ctrl+D shortcut specification
|
56
|
+
# and return a javax.swing.KeyStroke
|
57
|
+
def parse_shortcut( sequence )
|
58
|
+
# munge keystroke to something getKeyStroke recognises
|
59
|
+
# file:///usr/share/doc/java-sdk-docs-1.6.0.10/html/api/javax/swing/KeyStroke.html#getKeyStroke%28java.lang.String%29
|
60
|
+
# Yes, the space MUST be last in the charset, otherwise Ctrl-" fails
|
61
|
+
modifiers = sequence.split( /[-+ ]/ )
|
62
|
+
last = modifiers.pop
|
63
|
+
|
64
|
+
modifier_mask = modifiers.inject(0) do |mask,value|
|
65
|
+
mask |
|
66
|
+
if value =~ /ctrl/i
|
67
|
+
java.awt.Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
|
68
|
+
else
|
69
|
+
eval( "java.awt.event.InputEvent::#{value.upcase}_DOWN_MASK" )
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
keystroke =
|
74
|
+
if last.length == 1
|
75
|
+
case last
|
76
|
+
# these two seem to break the KeyStroke parsing algorithm
|
77
|
+
when "'"
|
78
|
+
javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent::VK_QUOTE, modifier_mask )
|
79
|
+
|
80
|
+
when '"'
|
81
|
+
javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent::VK_QUOTE, modifier_mask | java.awt.event.InputEvent::SHIFT_DOWN_MASK )
|
82
|
+
|
83
|
+
# the conversion in else doesn't work for these
|
84
|
+
when '['
|
85
|
+
javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent::VK_OPEN_BRACKET, modifier_mask )
|
86
|
+
|
87
|
+
when ']'
|
88
|
+
javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent::VK_CLOSE_BRACKET, modifier_mask )
|
89
|
+
|
90
|
+
when ';'
|
91
|
+
javax.swing.KeyStroke.getKeyStroke( java.awt.event.KeyEvent::VK_SEMICOLON, modifier_mask )
|
92
|
+
|
93
|
+
else
|
94
|
+
keystring = javax.swing.KeyStroke.getKeyStroke( java.lang.Character.new( last.to_char ), modifier_mask ).toString
|
95
|
+
puts "keystring: #{keystring.inspect}"
|
96
|
+
# have to do this conversion for Mac OS X
|
97
|
+
javax.swing.KeyStroke.getKeyStroke( keystring.gsub( /typed/, 'pressed' ) )
|
98
|
+
end
|
99
|
+
else
|
100
|
+
# F keys
|
101
|
+
# insert, delete, tab etc
|
102
|
+
found = java.awt.event.KeyEvent.constants.grep( /#{last}/i )
|
103
|
+
raise "too many options for #{sequence}: #{found.inspect}" if found.size != 1
|
104
|
+
javax.swing.KeyStroke.getKeyStroke( eval( "java.awt.event.KeyEvent::#{found.first}" ), modifier_mask )
|
105
|
+
end
|
106
|
+
puts "keystroke: #{keystroke.inspect}"
|
107
|
+
keystroke || raise( "unknown keystroke #{sequence} => #{modifiers.inspect} #{last}" )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# dummy class for creating a menu separator
|
112
|
+
class Separator < Action
|
113
|
+
def initialize
|
114
|
+
super(nil)
|
115
|
+
end
|
116
|
+
|
117
|
+
def shortcut
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def menu_item
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'clevic/action_builder.rb'
|
2
|
+
require 'clevic/swing/action.rb'
|
3
|
+
require 'clevic/swing/extensions.rb'
|
4
|
+
|
5
|
+
require 'changes'
|
6
|
+
|
7
|
+
module Clevic
|
8
|
+
|
9
|
+
module ActionBuilder
|
10
|
+
# Create a new separator and add a new separator.
|
11
|
+
def separator
|
12
|
+
Separator.new.tap do |action|
|
13
|
+
add_action action
|
14
|
+
collect_actions << action
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_action( &block )
|
19
|
+
Action.new( self ).tap( &block )
|
20
|
+
end
|
21
|
+
|
22
|
+
# set up the code to be executed when an action is triggered,
|
23
|
+
def action_method_or_block( action, options, &block )
|
24
|
+
# connect the action to some code
|
25
|
+
if options.has_key?( :method )
|
26
|
+
action.handler do |event|
|
27
|
+
puts "#{__FILE__}:#{__LINE__}:action.name: #{action.name.inspect}"
|
28
|
+
action_triggered do
|
29
|
+
# active is from Qt checkbox-menu-items
|
30
|
+
send_args = [ options[:method], options.has_key?( :checkable ) ? action.menu_item.selected? : nil ].compact
|
31
|
+
send( *send_args )
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
unless block.nil?
|
36
|
+
# TODO not sure why triggered is outside here, but not in the method section
|
37
|
+
action_triggered do
|
38
|
+
action.handler do |event|
|
39
|
+
yield( event )
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end # Clevic
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'clevic/swing/delegate'
|
2
|
+
|
3
|
+
module Clevic
|
4
|
+
|
5
|
+
class BooleanDelegate < Delegate
|
6
|
+
def init_component( cell_editor )
|
7
|
+
editor.selected = attribute_value
|
8
|
+
end
|
9
|
+
|
10
|
+
def editor
|
11
|
+
@editor ||= javax.swing.JCheckBox.new.tap do |e|
|
12
|
+
# TODO this is common to all delegates
|
13
|
+
e.horizontal_alignment = field.swing_alignment
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def value
|
18
|
+
editor.selected
|
19
|
+
end
|
20
|
+
|
21
|
+
def native
|
22
|
+
java.lang.Boolean
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
#~ require 'clevic/search_dialog.rb'
|
2
|
+
require 'clevic/view'
|
3
|
+
require 'clevic/swing/action_builder'
|
4
|
+
|
5
|
+
module Clevic
|
6
|
+
|
7
|
+
=begin rdoc
|
8
|
+
The main application class. Display one tabs for each descendant of Clevic::View
|
9
|
+
in Clevic::View.order. DefaultView classes created by Clevic::Record are included.
|
10
|
+
=end
|
11
|
+
class Browser < javax.swing.JFrame
|
12
|
+
#~ slots *%w{dump() refresh_table() filter_by_current(bool) next_tab() previous_tab()}
|
13
|
+
|
14
|
+
attr_reader :menu_edit, :menu_search, :menu_table
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super
|
18
|
+
|
19
|
+
# set OSX application title
|
20
|
+
java.lang.System.setProperty( "com.apple.mrj.application.apple.menu.about.name", title_string )
|
21
|
+
|
22
|
+
self.jmenu_bar = menu_bar
|
23
|
+
self.icon_image = icon
|
24
|
+
|
25
|
+
# add the tables tab
|
26
|
+
add( tables_tab, java.awt.BorderLayout::CENTER )
|
27
|
+
|
28
|
+
# add the status bar
|
29
|
+
add( status_bar, java.awt.BorderLayout::SOUTH )
|
30
|
+
|
31
|
+
load_views
|
32
|
+
update_menus
|
33
|
+
self.title = title_string
|
34
|
+
end
|
35
|
+
|
36
|
+
def title_string
|
37
|
+
[database_name, 'Clevic'].compact.join ' '
|
38
|
+
end
|
39
|
+
|
40
|
+
def menu_bar
|
41
|
+
javax.swing.JMenuBar.new.tap do |menu_bar|
|
42
|
+
menu_bar << javax.swing.JMenu.new( 'File' ).tap do |menu|
|
43
|
+
menu.mnemonic = java.awt.event.KeyEvent::VK_F
|
44
|
+
menu << "Open"
|
45
|
+
menu << "Close"
|
46
|
+
end
|
47
|
+
|
48
|
+
@menu_edit = javax.swing.JMenu.new( 'Edit' ).tap {|m| m.mnemonic = java.awt.event.KeyEvent::VK_E}
|
49
|
+
menu_bar << menu_edit
|
50
|
+
|
51
|
+
@menu_search = javax.swing.JMenu.new( 'Search' ).tap {|m| m.mnemonic = java.awt.event.KeyEvent::VK_S}
|
52
|
+
menu_bar << menu_search
|
53
|
+
|
54
|
+
@menu_table = javax.swing.JMenu.new( 'Table' ).tap do |menu|
|
55
|
+
menu.mnemonic = java.awt.event.KeyEvent::VK_T
|
56
|
+
menu << Action.new( self ) do |action|
|
57
|
+
action.name = :next_tab
|
58
|
+
action.text = "&Next"
|
59
|
+
action.shortcut = "Ctrl+Tab"
|
60
|
+
action.handler do |event|
|
61
|
+
puts "next tab"
|
62
|
+
next_tab
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
menu << Action.new( self ) do |action|
|
67
|
+
action.name = :previous_tab
|
68
|
+
action.text = "&Previous"
|
69
|
+
action.shortcut = "Shift+Ctrl+Tab"
|
70
|
+
action.handler do |event|
|
71
|
+
puts "previous tab"
|
72
|
+
previous_tab
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if $options[:debug]
|
77
|
+
menu << Action.new( self ) do |action|
|
78
|
+
action.name = :dump
|
79
|
+
action.text = "&Dump"
|
80
|
+
action.shortcut = "Ctrl+D"
|
81
|
+
action.handler do |event|
|
82
|
+
dump
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
menu_bar << @menu_table
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def icon
|
92
|
+
@icon ||=
|
93
|
+
begin
|
94
|
+
icon_path = Pathname.new( __FILE__ ).parent.parent + "icons/icon.png"
|
95
|
+
raise "icon.png not found" unless icon_path.file?
|
96
|
+
javax.swing.ImageIcon.new( icon_path.realpath.to_s ).image
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def tables_tab
|
101
|
+
@tables_tab ||= javax.swing.JTabbedPane.new.tap do |tables_tab|
|
102
|
+
# tell tab to not take focus
|
103
|
+
tables_tab.focusable = false
|
104
|
+
|
105
|
+
# tab navigation
|
106
|
+
tables_tab.add_change_listener do |change_event|
|
107
|
+
puts "change_event: #{change_event.source.inspect}"
|
108
|
+
puts "change_event.source.selected_index: #{change_event.source.selected_index.inspect}"
|
109
|
+
current_changed
|
110
|
+
# TODO tell exiting tab to save currently editing row/cell
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def status_bar
|
116
|
+
@status_bar ||= javax.swing.JLabel.new.tap do |status_bar|
|
117
|
+
status_bar.horizontal_alignment = javax.swing.SwingConstants::RIGHT
|
118
|
+
# just so the bar actually displays
|
119
|
+
status_bar.text = "Welcome to Clevic"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def status_bar_timer
|
124
|
+
@status_bar_timer ||= javax.swing.Timer.new( 15000, nil ).tap do |timer|
|
125
|
+
timer.repeats = false
|
126
|
+
# This is only for 1.6
|
127
|
+
#~ timer.action_command = 'hide_status_message'
|
128
|
+
timer.add_action_listener do |event|
|
129
|
+
status_bar.text = nil
|
130
|
+
timer.stop
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Set the main window title to the name of the database, if we can find it.
|
136
|
+
def database_name
|
137
|
+
table_view.model.entity_class.db.url rescue ''
|
138
|
+
end
|
139
|
+
|
140
|
+
# called by current_changed to update the Edit menu to the menus
|
141
|
+
# defined by the currently selected view
|
142
|
+
def update_menus
|
143
|
+
# update edit menu
|
144
|
+
menu_edit.remove_all
|
145
|
+
|
146
|
+
# do the model-specific menu items first
|
147
|
+
table_view.model_actions.each do |action|
|
148
|
+
menu_edit << action
|
149
|
+
end
|
150
|
+
|
151
|
+
# now do the generic edit items
|
152
|
+
table_view.edit_actions.each do |action|
|
153
|
+
menu_edit << action
|
154
|
+
end
|
155
|
+
|
156
|
+
# update search menu
|
157
|
+
menu_search.remove_all
|
158
|
+
table_view.search_actions.each do |action|
|
159
|
+
menu_search << action
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# activated by Ctrl-Shift-D for debugging
|
164
|
+
def dump
|
165
|
+
puts "table_view.model: #{table_view.model.inspect}"
|
166
|
+
puts "table_view.model.entity_class: #{table_view.model.entity_class.inspect}"
|
167
|
+
end
|
168
|
+
|
169
|
+
# return the Clevic::TableView object in the currently displayed tab
|
170
|
+
def table_view
|
171
|
+
tables_tab.selected_component
|
172
|
+
end
|
173
|
+
|
174
|
+
# slot to handle Ctrl-Tab and move to next tab, or wrap around
|
175
|
+
def next_tab
|
176
|
+
tables_tab.selected_index =
|
177
|
+
if tables_tab.selected_index >= tables_tab.count - 1
|
178
|
+
0
|
179
|
+
else
|
180
|
+
tables_tab.selected_index + 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# slot to handle Ctrl-Backtab and move to previous tab, or wrap around
|
185
|
+
def previous_tab
|
186
|
+
tables_tab.selected_index =
|
187
|
+
if tables_tab.selected_index <= 0
|
188
|
+
tables_tab.count - 1
|
189
|
+
else
|
190
|
+
tables_tab.selected_index - 1
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# slot to handle the currentChanged signal from tables_tab, and
|
195
|
+
# set focus on the grid
|
196
|
+
def current_changed
|
197
|
+
update_menus
|
198
|
+
table_view.request_focus
|
199
|
+
end
|
200
|
+
|
201
|
+
# Create the tabs, each with a collection for a particular entity class.
|
202
|
+
# views come from Clevic::View.order
|
203
|
+
def load_views
|
204
|
+
views = Clevic::View.views
|
205
|
+
Kernel.raise "no views to display" if views.empty?
|
206
|
+
|
207
|
+
# Add all existing model objects as tabs, one each
|
208
|
+
views.each do |view_class|
|
209
|
+
begin
|
210
|
+
view = view_class.new
|
211
|
+
unless view.entity_class.table_exists?
|
212
|
+
puts "Browser::load_views: No table for #{view.entity_class.inspect}"
|
213
|
+
next
|
214
|
+
end
|
215
|
+
|
216
|
+
# create the the table_view and the table_model for the entity_class
|
217
|
+
tab = Clevic::TableView.new( view )
|
218
|
+
|
219
|
+
# add a new tab
|
220
|
+
tables_tab.add( tab.title, tab )
|
221
|
+
|
222
|
+
# add the table to the Table menu
|
223
|
+
menu_table << Action.new( self ) do |action|
|
224
|
+
action.text = tab.title
|
225
|
+
action.handler do
|
226
|
+
tables_tab.current = tab
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
init_connections( tab )
|
231
|
+
rescue Exception => e
|
232
|
+
puts "UI from #{view} will not be available: #{e.message}"
|
233
|
+
puts e.backtrace
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def init_connections( tab )
|
239
|
+
tab.emit_status_text do |msg|
|
240
|
+
status_bar.text = msg
|
241
|
+
# hide the message after a while.
|
242
|
+
status_bar_timer.start
|
243
|
+
end
|
244
|
+
|
245
|
+
# handle filter status changed, so we can provide a visual indication
|
246
|
+
tab.emit_filter_status do |status|
|
247
|
+
# update the tab, so there's a visual indication of filtering
|
248
|
+
filter_title = ( tab.filtered? ? '| ' : '' ) + tab.title
|
249
|
+
tables_tab.set_title_at( tables_tab.selected_index, filter_title )
|
250
|
+
|
251
|
+
if tab.filtered?
|
252
|
+
tables_tab.set_tool_tip_text_at( tables_tab.selected_index, tab.filtered.status_message )
|
253
|
+
else
|
254
|
+
tables_tab.set_tool_tip_text_at( tables_tab.selected_index, nil )
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# make sure all outstanding records are saved
|
260
|
+
def save_all
|
261
|
+
tables_tab.each {|x| x.save_row( x.current_index ) }
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.run( args )
|
265
|
+
# make it more appley
|
266
|
+
java.lang.System.setProperty( "apple.laf.useScreenMenuBar", "true" )
|
267
|
+
javax.swing.UIManager.setLookAndFeel( javax.swing.UIManager.getSystemLookAndFeelClassName() )
|
268
|
+
|
269
|
+
# load models
|
270
|
+
args.each do |arg|
|
271
|
+
load_models( Pathname.new( arg ) )
|
272
|
+
end
|
273
|
+
|
274
|
+
# make top-level UI
|
275
|
+
browser = Browser.new
|
276
|
+
browser.default_close_operation = javax.swing.JFrame::EXIT_ON_CLOSE
|
277
|
+
browser.pack
|
278
|
+
browser.visible = true
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|