redcar 0.3.4.3 → 0.3.5

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.
Files changed (196) hide show
  1. data/CHANGES +45 -0
  2. data/README.md +2 -1
  3. data/ROADMAP.md +0 -1
  4. data/Rakefile +10 -4
  5. data/bin/redcar +2 -2
  6. data/lib/openssl/build.properties +7 -0
  7. data/lib/plugin_manager/lib/plugin_manager.rb +10 -0
  8. data/lib/plugin_manager/lib/plugin_manager/plugin_definition.rb +1 -13
  9. data/lib/redcar.rb +12 -8
  10. data/lib/redcar/installer.rb +16 -15
  11. data/lib/redcar/ruby_extensions.rb +146 -1
  12. data/lib/redcar/runner.rb +16 -7
  13. data/lib/redcar/usage.rb +4 -7
  14. data/lib/redcar_quick_start.rb +5 -5
  15. data/lib/regex_replace.rb +0 -7
  16. data/plugins/application/features/step_definitions/command_steps.rb +5 -0
  17. data/plugins/application/features/step_definitions/dialog_steps.rb +5 -0
  18. data/plugins/application/features/step_definitions/filter_list_dialog_steps.rb +38 -0
  19. data/plugins/application/features/step_definitions/window_steps.rb +1 -1
  20. data/plugins/application/features/support/env.rb +44 -8
  21. data/plugins/application/lib/application.rb +32 -33
  22. data/plugins/application/lib/application/command.rb +32 -2
  23. data/plugins/application/lib/application/command/executor.rb +2 -12
  24. data/plugins/application/lib/application/dialog.rb +14 -14
  25. data/plugins/application/lib/application/event_spewer.rb +32 -0
  26. data/plugins/application/lib/application/menu.rb +5 -5
  27. data/plugins/application/lib/application/menu/builder.rb +5 -0
  28. data/plugins/application/lib/application/menu/lazy_menu.rb +24 -0
  29. data/plugins/application/lib/application/notebook.rb +4 -3
  30. data/plugins/application/lib/application/tab.rb +6 -2
  31. data/plugins/application/lib/application/window.rb +8 -4
  32. data/plugins/application/spec/application/menu/builder_spec.rb +17 -1
  33. data/plugins/application/spec/application/notebook_spec.rb +1 -1
  34. data/plugins/application_swt/build.xml +74 -0
  35. data/plugins/application_swt/lib/application_swt.rb +79 -0
  36. data/plugins/application_swt/lib/application_swt/cucumber_patches.rb +6 -1
  37. data/plugins/application_swt/lib/application_swt/dialog_adapter.rb +25 -17
  38. data/plugins/application_swt/lib/application_swt/dialogs/filter_list_dialog_controller.rb +50 -12
  39. data/plugins/application_swt/lib/application_swt/html_tab.rb +20 -0
  40. data/plugins/application_swt/lib/application_swt/menu.rb +26 -2
  41. data/plugins/application_swt/lib/application_swt/notebook.rb +10 -12
  42. data/plugins/application_swt/lib/application_swt/window.rb +11 -11
  43. data/plugins/application_swt/src/com/redcareditor/application_swt/CocoaUIEnhancer.java +313 -0
  44. data/plugins/auto_completer/lib/auto_completer.rb +74 -67
  45. data/plugins/auto_completer/lib/auto_completer/current_document_completion_source.rb +19 -0
  46. data/plugins/auto_completer/lib/auto_completer/document_controller.rb +2 -2
  47. data/plugins/auto_completer/lib/auto_completer/word_list.rb +8 -1
  48. data/plugins/auto_indenter/features/ruby_style_indentation.feature +24 -0
  49. data/plugins/auto_indenter/features/step_definitions/indentation_steps.rb +6 -0
  50. data/plugins/auto_indenter/features/support/env.rb +2 -0
  51. data/plugins/auto_indenter/lib/auto_indenter.rb +86 -0
  52. data/plugins/auto_indenter/lib/auto_indenter/analyzer.rb +91 -0
  53. data/plugins/auto_indenter/lib/auto_indenter/commands.rb +34 -0
  54. data/plugins/auto_indenter/lib/auto_indenter/document_controller.rb +67 -12
  55. data/plugins/auto_indenter/lib/auto_indenter/rules.rb +41 -0
  56. data/plugins/auto_indenter/spec/auto_indenter/analyzer_spec.rb +151 -0
  57. data/plugins/auto_indenter/spec/spec_helper.rb +5 -0
  58. data/plugins/auto_pairer/lib/auto_pairer.rb +1 -0
  59. data/plugins/auto_pairer/lib/auto_pairer/document_controller.rb +43 -42
  60. data/plugins/auto_pairer/lib/auto_pairer/pairs_for_scope.rb +1 -5
  61. data/plugins/core/lib/core.rb +12 -1
  62. data/plugins/core/lib/core/observable.rb +7 -7
  63. data/plugins/core/lib/core/persistent_cache.rb +14 -2
  64. data/plugins/core/lib/core/plugin.rb +7 -0
  65. data/plugins/core/lib/core/resource.rb +78 -0
  66. data/plugins/core/lib/core/task.rb +62 -0
  67. data/plugins/core/lib/core/task_queue.rb +72 -0
  68. data/plugins/core/spec/core/resource_spec.rb +124 -0
  69. data/plugins/core/spec/core/task_queue_spec.rb +202 -0
  70. data/plugins/core/spec/spec_helper.rb +23 -1
  71. data/plugins/declarations/TODO +3 -0
  72. data/plugins/declarations/lib/declarations.rb +144 -0
  73. data/plugins/declarations/lib/declarations/completion_source.rb +22 -0
  74. data/plugins/declarations/lib/declarations/file.rb +68 -0
  75. data/plugins/declarations/lib/declarations/parser.rb +94 -0
  76. data/plugins/declarations/lib/declarations/select_tag_dialog.rb +44 -0
  77. data/plugins/declarations/plugin.rb +7 -0
  78. data/plugins/declarations/spec/declarations/file_spec.rb +62 -0
  79. data/plugins/declarations/spec/fixtures/federalist.rb +15 -0
  80. data/plugins/declarations/spec/spec_helper.rb +4 -0
  81. data/plugins/edit_view/features/indentation_commands.feature +40 -0
  82. data/plugins/edit_view/features/line_delimiter.feature +40 -0
  83. data/plugins/edit_view/features/step_definitions/editing_steps.rb +16 -4
  84. data/plugins/edit_view/features/step_definitions/notebook_steps.rb +1 -1
  85. data/plugins/edit_view/features/step_definitions/tab_steps.rb +1 -1
  86. data/plugins/edit_view/features/step_definitions/window_steps.rb +5 -1
  87. data/plugins/edit_view/features/support/env.rb +3 -5
  88. data/plugins/edit_view/features/undo_and_redo.feature +21 -0
  89. data/plugins/edit_view/lib/edit_view.rb +57 -4
  90. data/plugins/edit_view/lib/edit_view/actions/arrow_keys.rb +19 -3
  91. data/plugins/edit_view/lib/edit_view/document.rb +46 -11
  92. data/plugins/edit_view/lib/edit_view/document/indentation.rb +35 -0
  93. data/plugins/edit_view/lib/edit_view/modified_tabs_checker.rb +35 -0
  94. data/plugins/edit_view/lib/edit_view/tab_settings.rb +13 -3
  95. data/plugins/edit_view/spec/edit_view/document/indentation_spec.rb +112 -0
  96. data/plugins/edit_view/spec/edit_view/document_spec.rb +22 -0
  97. data/plugins/edit_view/spec/spec_helper.rb +1 -0
  98. data/plugins/edit_view_swt/lib/edit_view_swt.rb +59 -7
  99. data/plugins/edit_view_swt/lib/edit_view_swt/document.rb +3 -3
  100. data/plugins/edit_view_swt/lib/edit_view_swt/word_movement.rb +2 -2
  101. data/plugins/edit_view_swt/vendor/java-mateview.rb +3 -2
  102. data/plugins/encryption/encryption.rb +13 -6
  103. data/plugins/execute_current_tab/lib/execute_current_tab.rb +25 -15
  104. data/plugins/html_view/assets/redcar.css +32 -1
  105. data/plugins/html_view/lib/html_view.rb +23 -3
  106. data/plugins/html_view/lib/html_view/html_tab.rb +4 -0
  107. data/plugins/my_plugin/lib/my_plugin.rb +4 -12
  108. data/plugins/plugin_manager_ui/lib/plugin_manager_ui.rb +1 -0
  109. data/plugins/plugin_manager_ui/views/index.html.erb +30 -37
  110. data/plugins/project/features/find_file.feature +75 -0
  111. data/plugins/project/features/open_and_save_files.feature +7 -7
  112. data/plugins/project/features/open_directory_tree.feature +11 -3
  113. data/plugins/project/features/refresh_directory_tree.feature +7 -1
  114. data/plugins/project/features/step_definitions/directory_steps.rb +11 -1
  115. data/plugins/project/features/step_definitions/file_steps.rb +10 -0
  116. data/plugins/project/features/support/env.rb +6 -1
  117. data/plugins/project/features/watch_for_modified_files.feature +79 -0
  118. data/plugins/project/lib/project.rb +72 -306
  119. data/plugins/project/lib/project/commands.rb +128 -0
  120. data/plugins/project/lib/project/dir_mirror.rb +5 -1
  121. data/plugins/project/lib/project/drb_service.rb +21 -31
  122. data/plugins/project/lib/project/file_list.rb +76 -0
  123. data/plugins/project/lib/project/file_mirror.rb +13 -1
  124. data/plugins/project/lib/project/find_file_dialog.rb +22 -52
  125. data/plugins/project/lib/project/manager.rb +210 -0
  126. data/plugins/project/lib/project/recent_directories.rb +16 -3
  127. data/plugins/project/plugin.rb +1 -1
  128. data/plugins/project/spec/fixtures/myproject/README +2 -0
  129. data/plugins/project/spec/fixtures/myproject/lib/foo_lib.rb +1 -0
  130. data/plugins/project/spec/fixtures/myproject/spec/foo_spec.rb +1 -0
  131. data/plugins/project/{features → spec}/fixtures/winter.txt +0 -0
  132. data/plugins/project/spec/project/dir_mirror_spec.rb +1 -12
  133. data/plugins/project/spec/project/file_list_spec.rb +140 -0
  134. data/plugins/project/spec/spec_helper.rb +20 -0
  135. data/plugins/redcar/plugin.rb +1 -0
  136. data/plugins/redcar/redcar.rb +254 -84
  137. data/plugins/redcar_debug/lib/redcar_debug.rb +58 -11
  138. data/plugins/redcar_debug/vendor/jruby-prof/README +46 -0
  139. data/plugins/redcar_debug/vendor/jruby-prof/Rakefile +36 -0
  140. data/plugins/redcar_debug/vendor/jruby-prof/build.xml +31 -0
  141. data/plugins/redcar_debug/vendor/jruby-prof/example/call_tree.html +22677 -0
  142. data/plugins/redcar_debug/vendor/jruby-prof/example/call_tree.txt +589 -0
  143. data/plugins/redcar_debug/vendor/jruby-prof/example/flat.txt +28 -0
  144. data/plugins/redcar_debug/vendor/jruby-prof/example/graph.html +1670 -0
  145. data/plugins/redcar_debug/vendor/jruby-prof/example/graph.txt +125 -0
  146. data/plugins/redcar_debug/vendor/jruby-prof/example/pidigits.rb +92 -0
  147. data/plugins/redcar_debug/vendor/jruby-prof/example/test.rb +28 -0
  148. data/plugins/redcar_debug/vendor/jruby-prof/example/test2.rb +29 -0
  149. data/plugins/redcar_debug/vendor/jruby-prof/example/test_exception.rb +28 -0
  150. data/plugins/redcar_debug/vendor/jruby-prof/example/test_overhead.rb +43 -0
  151. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof.rb +66 -0
  152. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/abstract_printer.rb +21 -0
  153. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/flat_text_printer.rb +35 -0
  154. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/graph_html_printer.rb +123 -0
  155. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/graph_text_printer.rb +45 -0
  156. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/invocation_set.rb +34 -0
  157. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/method.rb +107 -0
  158. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/profile_invocation.rb +43 -0
  159. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/simple_tree_printer.rb +27 -0
  160. data/plugins/redcar_debug/vendor/jruby-prof/lib/jruby-prof/tree_html_printer.rb +144 -0
  161. data/plugins/redcar_debug/vendor/jruby-prof/src/org/jruby/prof/Invocation.java +14 -0
  162. data/plugins/redcar_debug/vendor/jruby-prof/src/org/jruby/prof/JRubyProf.java +94 -0
  163. data/plugins/redcar_debug/vendor/jruby-prof/src/org/jruby/prof/ProfEventHook.java +49 -0
  164. data/plugins/redcar_debug/vendor/jruby-prof/templates/graph_row.html.erb +18 -0
  165. data/plugins/redcar_debug/vendor/jruby-prof/test/basic_test.rb +291 -0
  166. data/plugins/redcar_debug/views/history.html.erb +33 -0
  167. data/plugins/redcar_debug/views/index.html.erb +33 -0
  168. data/plugins/repl/lib/repl/internal_mirror.rb +3 -15
  169. data/plugins/repl/spec/repl/internal_mirror_spec.rb +2 -2
  170. data/plugins/snippets/lib/snippets.rb +0 -1
  171. data/plugins/snippets/lib/snippets/document_controller.rb +7 -1
  172. data/plugins/task_manager/lib/task_manager.rb +28 -0
  173. data/plugins/task_manager/plugin.rb +11 -0
  174. data/plugins/task_manager/views/index.html.erb +67 -0
  175. data/plugins/textmate/lib/textmate.rb +17 -21
  176. data/plugins/textmate/lib/textmate/plist.rb +1 -2
  177. data/plugins/textmate/lib/textmate/preference.rb +5 -1
  178. data/plugins/textmate/lib/textmate/snippet.rb +6 -1
  179. data/plugins/tree_view_swt/lib/tree_view_swt.rb +0 -6
  180. data/textmate/Bundles/Cucumber.tmbundle/Preferences/Comments.tmPreferences +1 -1
  181. data/textmate/Bundles/Cucumber.tmbundle/Preferences/next_Cucumber_Plain_Text_Feature_Completions.tmPreferences +30 -0
  182. data/textmate/Bundles/Cucumber.tmbundle/Preferences/next_Symbol_list___Scenario.tmPreferences +19 -0
  183. data/textmate/Bundles/Cucumber.tmbundle/Syntaxes/next_Cucumber_Plain_Text_Feature.tmLanguage +221 -0
  184. data/textmate/Bundles/Cucumber.tmbundle/Syntaxes/next_Cucumber_Steps.tmLanguage +424 -0
  185. data/textmate/Bundles/Cucumber.tmbundle/Syntaxes/plaintext_template.erb +19 -77
  186. data/textmate/Bundles/Cucumber.tmbundle/info.plist +1 -20
  187. data/textmate/Bundles/Perl.tmbundle/Syntaxes/Perl.plist +1 -1
  188. data/textmate/Themes/Emacs Strict.tmTheme +241 -0
  189. data/textmate/Themes/IR_White.tmTheme +792 -0
  190. data/textmate/Themes/Monokai.tmTheme +291 -0
  191. data/textmate/Themes/WhysPoignant.tmTheme +191 -0
  192. metadata +92 -7
  193. data/plugins/application/features/main_window.feature +0 -8
  194. data/plugins/project/lib/project/project_command.rb +0 -5
  195. data/textmate/Bundles/Cucumber.tmbundle/Snippets/Scenario.tmSnippet +0 -22
  196. data/textmate/Bundles/Cucumber.tmbundle/Snippets/Story.tmSnippet +0 -25
@@ -2,7 +2,10 @@
2
2
  module Cucumber
3
3
  module Ast
4
4
  class StepInvocation #:nodoc:#
5
-
5
+ class << self
6
+ attr_accessor :wait_time
7
+ end
8
+
6
9
  def invoke(step_mother, options)
7
10
  block = Swt::RRunnable.new do
8
11
  find_step_match!(step_mother)
@@ -28,6 +31,8 @@ module Cucumber
28
31
  if ENV["SLOW_CUKES"]
29
32
  sleep ENV["SLOW_CUKES"].to_f
30
33
  end
34
+ sleep(Cucumber::Ast::StepInvocation.wait_time || 0)
35
+ Cucumber::Ast::StepInvocation.wait_time = nil
31
36
  end
32
37
  end
33
38
  end
@@ -1,16 +1,16 @@
1
1
  module Redcar
2
2
  class ApplicationSWT
3
3
  class DialogAdapter
4
- def open_file(window, options)
5
- file_dialog(window, Swt::SWT::OPEN, options)
4
+ def open_file(options)
5
+ file_dialog(Swt::SWT::OPEN, options)
6
6
  end
7
7
 
8
- def open_directory(window, options)
9
- directory_dialog(window, options)
8
+ def open_directory(options)
9
+ directory_dialog(options)
10
10
  end
11
11
 
12
- def save_file(window, options)
13
- file_dialog(window, Swt::SWT::SAVE, options)
12
+ def save_file(options)
13
+ file_dialog(Swt::SWT::SAVE, options)
14
14
  end
15
15
 
16
16
  MESSAGE_BOX_TYPES = {
@@ -40,14 +40,14 @@ module Redcar
40
40
  :abort_retry_ignore => [:abort, :retry, :ignore]
41
41
  }
42
42
 
43
- def message_box(window, text, options)
43
+ def message_box(text, options)
44
44
  styles = 0
45
45
  styles = styles | MESSAGE_BOX_TYPES[options[:type]] if options[:type]
46
46
  if options[:buttons]
47
47
  buttons = MESSAGE_BOX_BUTTON_COMBOS[options[:buttons]]
48
48
  buttons.each {|b| styles = styles | BUTTONS[b] }
49
49
  end
50
- dialog = Swt::Widgets::MessageBox.new(window.controller.shell, styles)
50
+ dialog = Swt::Widgets::MessageBox.new(parent_shell, styles)
51
51
  dialog.set_message(text)
52
52
  result = nil
53
53
  Redcar.app.protect_application_focus do
@@ -75,12 +75,12 @@ module Redcar
75
75
 
76
76
  def createShell
77
77
  super
78
- p [:in, get_shell]
79
78
  end
80
79
  end
81
80
 
82
- def input(window, title, message, initial_value, &block)
83
- dialog = JFace::Dialogs::InputDialog.new(window.controller.shell,
81
+ def input(title, message, initial_value, &block)
82
+ dialog = JFace::Dialogs::InputDialog.new(
83
+ parent_shell,
84
84
  title, message, initial_value) do |text|
85
85
  block ? block[text] : nil
86
86
  end
@@ -89,16 +89,16 @@ module Redcar
89
89
  {:button => button, :value => dialog.getValue}
90
90
  end
91
91
 
92
- def tool_tip(window, message)
93
- tool_tip = Swt::Widgets::ToolTip.new(window.controller.shell, Swt::SWT::ICON_INFORMATION)
92
+ def tool_tip(message)
93
+ tool_tip = Swt::Widgets::ToolTip.new(parent_shell, Swt::SWT::ICON_INFORMATION)
94
94
  tool_tip.set_message(message)
95
95
  tool_tip.set_visible(true)
96
96
  end
97
97
 
98
98
  private
99
99
 
100
- def file_dialog(window, type, options)
101
- dialog = Swt::Widgets::FileDialog.new(window.controller.shell, type)
100
+ def file_dialog(type, options)
101
+ dialog = Swt::Widgets::FileDialog.new(parent_shell, type)
102
102
  if options[:filter_path]
103
103
  dialog.set_filter_path(options[:filter_path])
104
104
  end
@@ -107,8 +107,8 @@ module Redcar
107
107
  end
108
108
  end
109
109
 
110
- def directory_dialog(window, options)
111
- dialog = Swt::Widgets::DirectoryDialog.new(window.controller.shell)
110
+ def directory_dialog(options)
111
+ dialog = Swt::Widgets::DirectoryDialog.new(parent_shell)
112
112
  if options[:filter_path]
113
113
  dialog.set_filter_path(options[:filter_path])
114
114
  end
@@ -116,6 +116,14 @@ module Redcar
116
116
  dialog.open
117
117
  end
118
118
  end
119
+
120
+ def parent_shell
121
+ if focussed_window = Redcar.app.focussed_window
122
+ focussed_window.controller.shell
123
+ else
124
+ Redcar.app.controller.fake_shell
125
+ end
126
+ end
119
127
  end
120
128
  end
121
129
  end
@@ -2,7 +2,13 @@ module Redcar
2
2
  class ApplicationSWT
3
3
  class FilterListDialogController
4
4
  include ReentryHelpers
5
-
5
+
6
+ class << self
7
+ # when set, the FilterListDialog is non-modal for testing
8
+ attr_writer :test_mode
9
+ def test_mode?; @test_mode; end
10
+ end
11
+
6
12
  class FilterListDialog < Dialogs::NoButtonsDialog
7
13
  attr_reader :list, :text
8
14
  attr_accessor :controller
@@ -14,12 +20,13 @@ module Redcar
14
20
 
15
21
  @text = Swt::Widgets::Text.new(composite, Swt::SWT::SINGLE | Swt::SWT::LEFT | Swt::SWT::ICON_CANCEL)
16
22
  @text.set_layout_data(Swt::Layout::RowData.new(400, 20))
17
- @list = Swt::Widgets::List.new(composite, Swt::SWT::SINGLE)
23
+ @list = Swt::Widgets::List.new(composite, Swt::SWT::V_SCROLL | Swt::SWT::H_SCROLL | Swt::SWT::SINGLE)
18
24
  @list.set_layout_data(Swt::Layout::RowData.new(400, 200))
19
25
  controller.attach_listeners
20
- controller.update_list
26
+ controller.update_list_sync
21
27
  get_shell.add_shell_listener(ShellListener.new(controller))
22
28
  ApplicationSWT.register_shell(get_shell)
29
+ ApplicationSWT.register_dialog(get_shell, self)
23
30
 
24
31
  @list.set_selection(0)
25
32
  end
@@ -57,6 +64,10 @@ module Redcar
57
64
  @model = model
58
65
  @dialog = FilterListDialog.new(Redcar.app.focussed_window.controller.shell)
59
66
  @dialog.controller = self
67
+ if FilterListDialogController.test_mode?
68
+ @dialog.setBlockOnOpen(false)
69
+ @dialog.setShellStyle(Swt::SWT::DIALOG_TRIM)
70
+ end
60
71
  attach_model_listeners
61
72
  end
62
73
 
@@ -81,42 +92,69 @@ module Redcar
81
92
  end
82
93
 
83
94
  def key_pressed(e)
84
- e.doit = @controller.key_pressed(e)
95
+ @controller.key_pressed(e)
85
96
  end
86
97
 
87
98
  def key_released(e)
88
99
  end
89
100
  end
90
101
 
102
+ class SelectionListener
103
+ def initialize(controller)
104
+ @controller = controller
105
+ end
106
+
107
+ def widgetDefaultSelected(e)
108
+ @controller.selected
109
+ end
110
+
111
+ def widgetSelected(e)
112
+ @controller.text_focus
113
+ end
114
+ end
115
+
91
116
  def attach_listeners
92
117
  @dialog.text.add_modify_listener(ModifyListener.new(self))
93
118
  @dialog.text.add_key_listener(KeyListener.new(self))
119
+ @dialog.list.add_selection_listener(SelectionListener.new(self))
94
120
  end
95
121
 
96
122
  def open
97
123
  @dialog.open
98
- @dialog = nil
124
+ @dialog = nil unless FilterListDialogController.test_mode?
99
125
  end
100
126
 
101
127
  def close
102
128
  @dialog.close
129
+ ApplicationSWT.unregister_dialog(@dialog)
130
+ @dialog = nil
103
131
  end
104
132
 
105
133
  def update_list
106
134
  @last_keypress = Time.now
107
135
  pause_time = FilterListDialogController.storage['pause_before_update_seconds']
108
- Swt::Widgets::Display.getCurrent.timerExec(pause_time*1000, Swt::RRunnable.new {
109
- if @dialog and @last_keypress and (Time.now - @last_keypress + pause_time) > pause_time
136
+ Swt::Widgets::Display.getCurrent.timerExec(pause_time*1000, Swt::RRunnable.new {
137
+ if @last_keypress and (Time.now - @last_keypress + pause_time) > pause_time
110
138
  @last_keypress = nil
111
- s = Time.now
112
- list = @model.update_list(@dialog.text.get_text)
113
- puts "update list took #{Time.now - s}s"
114
- populate_list(list)
115
- @dialog.list.set_selection(0)
139
+ update_list_sync
116
140
  end
117
141
  })
118
142
  end
119
143
 
144
+ def update_list_sync
145
+ if @dialog
146
+ s = Time.now
147
+ list = @model.update_list(@dialog.text.get_text)
148
+ populate_list(list)
149
+ @dialog.list.set_selection(0)
150
+ text_focus
151
+ end
152
+ end
153
+
154
+ def text_focus
155
+ @dialog.text.set_focus
156
+ end
157
+
120
158
  def selected
121
159
  @model.selected(@dialog.list.get_selection.first, @dialog.list.get_selection_index)
122
160
  end
@@ -20,6 +20,7 @@ module Redcar
20
20
  end
21
21
  @widget = @browser
22
22
  @item.control = @widget
23
+ add_listeners
23
24
  end
24
25
 
25
26
  # Focuses the Browser tab within the CTabFolder, and gives the keyboard
@@ -34,6 +35,25 @@ module Redcar
34
35
  @browser.dispose
35
36
  super
36
37
  end
38
+
39
+ class LocationListener
40
+ def initialize(html_tab)
41
+ @html_tab = html_tab
42
+ end
43
+
44
+ def changing(event)
45
+ if event.location =~ %r{file:///controller/([^/]*)(/(.*))?}
46
+ event.doit = false
47
+ @html_tab.controller_action($1, $2)
48
+ end
49
+ end
50
+
51
+ def changed(*_); end
52
+ end
53
+
54
+ def add_listeners
55
+ @browser.add_location_listener(LocationListener.new(@model))
56
+ end
37
57
  end
38
58
  end
39
59
  end
@@ -16,17 +16,20 @@ module Redcar
16
16
  end
17
17
 
18
18
  def initialize(window, menu_model, keymap, type, options={})
19
+ s = Time.now
19
20
  unless Menu.menu_types.include?(type)
20
21
  raise "type should be in #{Menu.menu_types.inspect}"
21
22
  end
22
23
  @window = window
23
24
  @keymap = keymap
24
25
  @menu_bar = Swt::Widgets::Menu.new(window.shell, type)
26
+ @menu_bar.set_visible(false)
25
27
  return unless menu_model
26
28
  @handlers = []
27
29
  @use_numbers = options[:numbers]
28
30
  @number = 1
29
31
  add_entries_to_menu(@menu_bar, menu_model)
32
+ #puts "ApplicationSWT::Menu initialize took #{Time.now - s}s"
30
33
  end
31
34
 
32
35
  def show
@@ -47,7 +50,16 @@ module Redcar
47
50
 
48
51
  def add_entries_to_menu(menu, menu_model)
49
52
  menu_model.each do |entry|
50
- if entry.is_a?(Redcar::Menu)
53
+ if entry.is_a?(Redcar::Menu::LazyMenu)
54
+ menu_header = Swt::Widgets::MenuItem.new(menu, Swt::SWT::CASCADE)
55
+ menu_header.text = entry.text
56
+ new_menu = Swt::Widgets::Menu.new(@window.shell, Swt::SWT::DROP_DOWN)
57
+ menu_header.menu = new_menu
58
+ menu_header.add_arm_listener do
59
+ new_menu.get_items.each {|i| i.dispose }
60
+ add_entries_to_menu(new_menu, entry)
61
+ end
62
+ elsif entry.is_a?(Redcar::Menu)
51
63
  menu_header = Swt::Widgets::MenuItem.new(menu, Swt::SWT::CASCADE)
52
64
  menu_header.text = entry.text
53
65
  new_menu = Swt::Widgets::Menu.new(@window.shell, Swt::SWT::DROP_DOWN)
@@ -67,6 +79,18 @@ module Redcar
67
79
  end
68
80
  end
69
81
  end
82
+
83
+ class ProcSelectionListener
84
+ def initialize(entry)
85
+ @entry = entry
86
+ end
87
+
88
+ def widget_selected(e)
89
+ @entry.command.call
90
+ end
91
+
92
+ alias :widget_default_selected :widget_selected
93
+ end
70
94
 
71
95
  def connect_proc_to_item(item, entry)
72
96
  if use_numbers? and Redcar.platform == :osx
@@ -75,7 +99,7 @@ module Redcar
75
99
  else
76
100
  item.text = entry.text
77
101
  end
78
- item.add_selection_listener { entry.command.call }
102
+ item.addSelectionListener(ProcSelectionListener.new(entry))
79
103
  end
80
104
 
81
105
  class SelectionListener
@@ -6,17 +6,16 @@ module Redcar
6
6
  attr_reader :tab_folder
7
7
 
8
8
  class CTabFolder2Listener
9
- include ListenerHelpers
10
-
11
9
  def initialize(controller)
12
10
  @controller = controller
13
11
  end
14
12
 
15
13
  def close(event)
16
- ignore_within_self do
17
- event.doit = false
18
- if event.item
19
- @controller.tab_widget_to_tab_model(event.item).close
14
+ if event.item
15
+ tab = @controller.tab_widget_to_tab_model(event.item)
16
+ unless Redcar.app.events.ignore?(:tab_close, tab)
17
+ event.doit = false
18
+ Redcar.app.events.create(:tab_close, tab)
20
19
  end
21
20
  end
22
21
  end
@@ -28,17 +27,16 @@ module Redcar
28
27
  end
29
28
 
30
29
  class SelectionListener
31
- include ListenerHelpers
32
-
33
30
  def initialize(controller)
34
31
  @controller = controller
35
32
  end
36
33
 
37
34
  def widgetSelected(event)
38
- ignore_within_self do
39
- event.doit = false
40
- if event.item
41
- @controller.tab_widget_to_tab_model(event.item).focus
35
+ if event.item
36
+ tab = @controller.tab_widget_to_tab_model(event.item)
37
+ unless Redcar.app.events.ignore?(:tab_focus, tab)
38
+ event.doit = false
39
+ Redcar.app.events.create(:tab_focus, tab)
42
40
  end
43
41
  end
44
42
  end
@@ -5,23 +5,21 @@ module Redcar
5
5
  attr_reader :shell, :window, :shell_listener
6
6
 
7
7
  class ShellListener
8
- include ReentryHelpers
9
-
10
8
  def initialize(controller)
11
- @controller = controller
9
+ @win = controller.window
12
10
  end
13
11
 
14
12
  def shell_closed(e)
15
- @controller.window.close
16
- @controller.window.ignore(:closing) do
13
+ unless Redcar.app.events.ignore?(:window_close, @win)
17
14
  e.doit = false
15
+ Redcar.app.events.create(:window_close, @win)
18
16
  end
19
17
  end
20
18
 
21
19
  def shell_activated(e)
22
- @controller.window.focus
23
- @controller.window.ignore(:focussing) do
20
+ unless Redcar.app.events.ignore?(:window_focus, @win)
24
21
  e.doit = false
22
+ Redcar.app.events.create(:window_focus, @win)
25
23
  end
26
24
  end
27
25
 
@@ -112,14 +110,16 @@ module Redcar
112
110
  end
113
111
 
114
112
  def refresh_menu
115
- @menu_controller = ApplicationSWT::Menu.new(self, @window.menu, @window.keymap, Swt::SWT::BAR)
113
+ old_menu_bar = shell.menu_bar
114
+ @menu_controller = ApplicationSWT::Menu.new(self, Redcar.app.main_menu, Redcar.app.main_keymap, Swt::SWT::BAR)
116
115
  shell.menu_bar = @menu_controller.menu_bar
116
+ old_menu_bar.dispose if old_menu_bar
117
117
  end
118
118
 
119
119
  def set_icon(path)
120
- icon = Swt::Graphics::Image.new(ApplicationSWT.display, path)
121
- shell.image = icon
122
- end
120
+ icon = Swt::Graphics::Image.new(ApplicationSWT.display, path)
121
+ shell.image = icon
122
+ end
123
123
 
124
124
  def bring_to_front
125
125
  @shell.set_minimized(false) # unminimize, just in case
@@ -0,0 +1,313 @@
1
+
2
+ package com.redcareditor.application_swt;
3
+
4
+ import java.lang.reflect.InvocationTargetException;
5
+ import java.lang.reflect.Method;
6
+
7
+ import org.eclipse.swt.SWT;
8
+ import org.eclipse.swt.internal.C;
9
+ import org.eclipse.swt.internal.Callback;
10
+ import org.eclipse.swt.widgets.Display;
11
+ import org.eclipse.swt.widgets.Listener;
12
+
13
+ /**
14
+ * Provide a hook to connecting the Preferences, About and Quit menu items of the Mac OS X
15
+ * Application menu when using the SWT Cocoa bindings.
16
+ * <p>
17
+ * This code does not require the Cocoa SWT JAR in order to be compiled as it uses reflection to
18
+ * access the Cocoa specific API methods. It does, however, depend on JFace (for IAction), but you
19
+ * could easily modify the code to use SWT Listeners instead in order to use this class in SWT only
20
+ * applications.
21
+ * </p>
22
+ * <p>
23
+ * This code was influenced by the <a
24
+ * href="http://www.simidude.com/blog/2008/macify-a-swt-application-in-a-cross-platform-way/"
25
+ * >CarbonUIEnhancer from Agynami</a> with the implementation being modified from the <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.ui.cocoa/src/org/eclipse/ui/internal/cocoa/CocoaUIEnhancer.java"
26
+ * >org.eclipse.ui.internal.cocoa.CocoaUIEnhancer</a>.
27
+ * </p>
28
+ * <p>
29
+ * This class works with both the 32-bit and 64-bit versions of the SWT Cocoa bindings.
30
+ * <p>
31
+ * <p>
32
+ * This class is released under the Eclipse Public License (<a href="http://www.eclipse.org/legal/epl-v10.html">EPL</a>).
33
+ */
34
+ public class CocoaUIEnhancer {
35
+
36
+ private static final long kAboutMenuItem = 0;
37
+ private static final long kPreferencesMenuItem = 2;
38
+ // private static final long kServicesMenuItem = 4;
39
+ // private static final long kHideApplicationMenuItem = 6;
40
+ private static final long kQuitMenuItem = 10;
41
+
42
+ static long sel_toolbarButtonClicked_;
43
+ static long sel_preferencesMenuItemSelected_;
44
+ static long sel_aboutMenuItemSelected_;
45
+ static Callback proc3Args;
46
+
47
+ final private String appName;
48
+
49
+ /**
50
+ * Class invoked via the Callback object to run the about and preferences actions.
51
+ * <p>
52
+ * If you don't use JFace in your application (SWT only), change the
53
+ * {@link org.eclipse.jface.action.IAction}s to {@link org.eclipse.swt.widgets.Listener}s.
54
+ * </p>
55
+ */
56
+ private static class MenuHookObject {
57
+ final Listener about;
58
+ final Listener pref;
59
+
60
+ public MenuHookObject( Listener about, Listener pref ) {
61
+ this.about = about;
62
+ this.pref = pref;
63
+ }
64
+
65
+ /**
66
+ * Will be called on 32bit SWT.
67
+ */
68
+ @SuppressWarnings( "unused" )
69
+ public int actionProc( int id, int sel, int arg0 ) {
70
+ return (int) actionProc( (long) id, (long) sel, (long) arg0 );
71
+ }
72
+
73
+ /**
74
+ * Will be called on 64bit SWT.
75
+ */
76
+ public long actionProc( long id, long sel, long arg0 ) {
77
+ if ( sel == sel_aboutMenuItemSelected_ ) {
78
+ about.handleEvent(null);
79
+ } else if ( sel == sel_preferencesMenuItemSelected_ ) {
80
+ pref.handleEvent(null);
81
+ } else {
82
+ // Unknown selection!
83
+ }
84
+ // Return value is not used.
85
+ return 99;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Construct a new CocoaUIEnhancer.
91
+ *
92
+ * @param appName
93
+ * The name of the application. It will be used to customize the About and Quit menu
94
+ * items. If you do not wish to customize the About and Quit menu items, just pass
95
+ * <tt>null</tt> here.
96
+ */
97
+ public CocoaUIEnhancer( String appName ) {
98
+ this.appName = appName;
99
+ }
100
+
101
+ /**
102
+ * Hook the given Listener to the Mac OS X application Quit menu and the IActions to the About
103
+ * and Preferences menus.
104
+ *
105
+ * @param display
106
+ * The Display to use.
107
+ * @param quitListener
108
+ * The listener to invoke when the Quit menu is invoked.
109
+ * @param aboutListener
110
+ * The listener to invoke when the About menu is invoked.
111
+ * @param preferencesListener
112
+ * The listener to invoke when the Preferences menu is invoked.
113
+ */
114
+ public void hookApplicationMenu( Display display, Listener quitListener, Listener aboutListener,
115
+ Listener preferencesListener ) {
116
+ // This is our callbackObject whose 'actionProc' method will be called when the About or
117
+ // Preferences menuItem is invoked.
118
+ MenuHookObject target = new MenuHookObject( aboutListener, preferencesListener );
119
+
120
+ try {
121
+ // Initialize the menuItems.
122
+ initialize( target );
123
+ } catch ( Exception e ) {
124
+ throw new IllegalStateException( e );
125
+ }
126
+
127
+ // Connect the quit/exit menu.
128
+ if ( !display.isDisposed() ) {
129
+ display.addListener( SWT.Close, quitListener );
130
+ }
131
+
132
+ // Schedule disposal of callback object
133
+ display.disposeExec( new Runnable() {
134
+ public void run() {
135
+ invoke( proc3Args, "dispose" );
136
+ }
137
+ } );
138
+ }
139
+
140
+ private void initialize( Object callbackObject )
141
+ throws Exception {
142
+
143
+ Class<?> osCls = classForName( "org.eclipse.swt.internal.cocoa.OS" );
144
+
145
+ // Register names in objective-c.
146
+ if ( sel_toolbarButtonClicked_ == 0 ) {
147
+ // sel_toolbarButtonClicked_ = registerName( osCls, "toolbarButtonClicked:" ); //$NON-NLS-1$
148
+ sel_preferencesMenuItemSelected_ = registerName( osCls, "preferencesMenuItemSelected:" ); //$NON-NLS-1$
149
+ sel_aboutMenuItemSelected_ = registerName( osCls, "aboutMenuItemSelected:" ); //$NON-NLS-1$
150
+ }
151
+
152
+ // Create an SWT Callback object that will invoke the actionProc method of our internal
153
+ // callbackObject.
154
+ proc3Args = new Callback( callbackObject, "actionProc", 3 ); //$NON-NLS-1$
155
+ Method getAddress = Callback.class.getMethod( "getAddress", new Class[0] );
156
+ Object object = getAddress.invoke( proc3Args, (Object[]) null );
157
+ long proc3 = convertToLong( object );
158
+ if ( proc3 == 0 ) {
159
+ SWT.error( SWT.ERROR_NO_MORE_CALLBACKS );
160
+ }
161
+
162
+ Class<?> nsmenuCls = classForName( "org.eclipse.swt.internal.cocoa.NSMenu" );
163
+ Class<?> nsmenuitemCls = classForName( "org.eclipse.swt.internal.cocoa.NSMenuItem" );
164
+ Class<?> nsstringCls = classForName( "org.eclipse.swt.internal.cocoa.NSString" );
165
+ Class<?> nsapplicationCls = classForName( "org.eclipse.swt.internal.cocoa.NSApplication" );
166
+
167
+ // Instead of creating a new delegate class in objective-c,
168
+ // just use the current SWTApplicationDelegate. An instance of this
169
+ // is a field of the Cocoa Display object and is already the target
170
+ // for the menuItems. So just get this class and add the new methods
171
+ // to it.
172
+ object = invoke( osCls, "objc_lookUpClass", new Object[] { "SWTApplicationDelegate" } );
173
+ long cls = convertToLong( object );
174
+
175
+ // Add the action callbacks for Preferences and About menu items.
176
+ invoke( osCls, "class_addMethod", new Object[] {
177
+ wrapPointer( cls ),
178
+ wrapPointer( sel_preferencesMenuItemSelected_ ),
179
+ wrapPointer( proc3 ),
180
+ "@:@" } ); //$NON-NLS-1$
181
+ invoke( osCls, "class_addMethod", new Object[] {
182
+ wrapPointer( cls ),
183
+ wrapPointer( sel_aboutMenuItemSelected_ ),
184
+ wrapPointer( proc3 ),
185
+ "@:@" } ); //$NON-NLS-1$
186
+
187
+ // Get the Mac OS X Application menu.
188
+ Object sharedApplication = invoke( nsapplicationCls, "sharedApplication" );
189
+ Object mainMenu = invoke( sharedApplication, "mainMenu" );
190
+ Object mainMenuItem = invoke( nsmenuCls, mainMenu, "itemAtIndex", new Object[] { wrapPointer( 0 ) } );
191
+ Object appMenu = invoke( mainMenuItem, "submenu" );
192
+
193
+ // Create the About <application-name> menu command
194
+ Object aboutMenuItem =
195
+ invoke( nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer( kAboutMenuItem ) } );
196
+ if ( appName != null ) {
197
+ Object nsStr = invoke( nsstringCls, "stringWith", new Object[] { "About " + appName } );
198
+ invoke( nsmenuitemCls, aboutMenuItem, "setTitle", new Object[] { nsStr } );
199
+ }
200
+ // Rename the quit action.
201
+ if ( appName != null ) {
202
+ Object quitMenuItem =
203
+ invoke( nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer( kQuitMenuItem ) } );
204
+ Object nsStr = invoke( nsstringCls, "stringWith", new Object[] { "Quit " + appName } );
205
+ invoke( nsmenuitemCls, quitMenuItem, "setTitle", new Object[] { nsStr } );
206
+ }
207
+
208
+ // Enable the Preferences menuItem.
209
+ Object prefMenuItem =
210
+ invoke( nsmenuCls, appMenu, "itemAtIndex", new Object[] { wrapPointer( kPreferencesMenuItem ) } );
211
+ invoke( nsmenuitemCls, prefMenuItem, "setEnabled", new Object[] { true } );
212
+
213
+ // Set the action to execute when the About or Preferences menuItem is invoked.
214
+ //
215
+ // We don't need to set the target here as the current target is the SWTApplicationDelegate
216
+ // and we have registerd the new selectors on it. So just set the new action to invoke the
217
+ // selector.
218
+ invoke( nsmenuitemCls, prefMenuItem, "setAction",
219
+ new Object[] { wrapPointer( sel_preferencesMenuItemSelected_ ) } );
220
+ invoke( nsmenuitemCls, aboutMenuItem, "setAction",
221
+ new Object[] { wrapPointer( sel_aboutMenuItemSelected_ ) } );
222
+ }
223
+
224
+ private long registerName( Class<?> osCls, String name )
225
+ throws IllegalArgumentException, SecurityException, IllegalAccessException,
226
+ InvocationTargetException, NoSuchMethodException {
227
+ Object object = invoke( osCls, "sel_registerName", new Object[] { name } );
228
+ return convertToLong( object );
229
+ }
230
+
231
+ private long convertToLong( Object object ) {
232
+ if ( object instanceof Integer ) {
233
+ Integer i = (Integer) object;
234
+ return i.longValue();
235
+ }
236
+ if ( object instanceof Long ) {
237
+ Long l = (Long) object;
238
+ return l.longValue();
239
+ }
240
+ return 0;
241
+ }
242
+
243
+ private static Object wrapPointer( long value ) {
244
+ Class<?> PTR_CLASS = C.PTR_SIZEOF == 8 ? long.class : int.class;
245
+ if ( PTR_CLASS == long.class ) {
246
+ return new Long( value );
247
+ } else {
248
+ return new Integer( (int) value );
249
+ }
250
+ }
251
+
252
+ private static Object invoke( Class<?> clazz, String methodName, Object[] args ) {
253
+ return invoke( clazz, null, methodName, args );
254
+ }
255
+
256
+ private static Object invoke( Class<?> clazz, Object target, String methodName, Object[] args ) {
257
+ try {
258
+ Class<?>[] signature = new Class<?>[args.length];
259
+ for ( int i = 0; i < args.length; i++ ) {
260
+ Class<?> thisClass = args[i].getClass();
261
+ if ( thisClass == Integer.class )
262
+ signature[i] = int.class;
263
+ else if ( thisClass == Long.class )
264
+ signature[i] = long.class;
265
+ else if ( thisClass == Byte.class )
266
+ signature[i] = byte.class;
267
+ else if ( thisClass == Boolean.class )
268
+ signature[i] = boolean.class;
269
+ else
270
+ signature[i] = thisClass;
271
+ }
272
+ Method method = clazz.getMethod( methodName, signature );
273
+ return method.invoke( target, args );
274
+ } catch ( Exception e ) {
275
+ throw new IllegalStateException( e );
276
+ }
277
+ }
278
+
279
+ private Class<?> classForName( String classname ) {
280
+ try {
281
+ Class<?> cls = Class.forName( classname );
282
+ return cls;
283
+ } catch ( ClassNotFoundException e ) {
284
+ throw new IllegalStateException( e );
285
+ }
286
+ }
287
+
288
+ private Object invoke( Class<?> cls, String methodName ) {
289
+ return invoke( cls, methodName, (Class<?>[]) null, (Object[]) null );
290
+ }
291
+
292
+ private Object invoke( Class<?> cls, String methodName, Class<?>[] paramTypes, Object... arguments ) {
293
+ try {
294
+ Method m = cls.getDeclaredMethod( methodName, paramTypes );
295
+ return m.invoke( null, arguments );
296
+ } catch ( Exception e ) {
297
+ throw new IllegalStateException( e );
298
+ }
299
+ }
300
+
301
+ private Object invoke( Object obj, String methodName ) {
302
+ return invoke( obj, methodName, (Class<?>[]) null, (Object[]) null );
303
+ }
304
+
305
+ private Object invoke( Object obj, String methodName, Class<?>[] paramTypes, Object... arguments ) {
306
+ try {
307
+ Method m = obj.getClass().getDeclaredMethod( methodName, paramTypes );
308
+ return m.invoke( obj, arguments );
309
+ } catch ( Exception e ) {
310
+ throw new IllegalStateException( e );
311
+ }
312
+ }
313
+ }