glimmer-cs-gladiator 0.8.0 → 0.8.1

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.
@@ -43,6 +43,7 @@ module Glimmer
43
43
  APP_ROOT = ::File.expand_path('../../../..', __FILE__)
44
44
  # TODO make sure COMMAND_KEY doesn't clash on Linux/Windows for CMD+CTRL shortcuts
45
45
  COMMAND_KEY = OS.mac? ? :command : :ctrl
46
+ CONTROL_KEY = OS.mac? ? :ctrl : :alt
46
47
  VERSION = ::File.read(::File.join(APP_ROOT, 'VERSION')).to_s.strip
47
48
  LICENSE = ::File.read(::File.join(APP_ROOT, 'LICENSE.txt')).to_s.strip
48
49
  ICON = ::File.expand_path(::File.join(APP_ROOT, 'images', 'glimmer-cs-gladiator-logo.png'))
@@ -106,7 +107,6 @@ module Glimmer
106
107
  display_about_dialog
107
108
  }
108
109
  on_quit {
109
- save_config
110
110
  project_dir.selected_child&.write_dirty_content
111
111
  display.swt_display.shells.each(&:close)
112
112
  }
@@ -115,7 +115,6 @@ module Glimmer
115
115
  focused_gladiator.handle_display_shortcut(key_event) if !focused_gladiator.nil? && key_event.widget.shell == focused_gladiator&.swt_widget
116
116
  }
117
117
  on_swt_Close {
118
- save_config
119
118
  project_dir.selected_child&.write_dirty_content
120
119
  }
121
120
  }
@@ -140,7 +139,7 @@ module Glimmer
140
139
  if Gladiator.drag && !@tab_folder2
141
140
  self.tab_folder1 = current_tab_folder
142
141
  @tab_folder_sash_form.content {
143
- self.current_tab_folder = self.tab_folder2 = tab_folder {}
142
+ self.current_tab_folder = self.tab_folder2 = text_editor_group_tab_folder
144
143
  @current_tab_folder.swt_widget.setData('proxy', @current_tab_folder)
145
144
  }
146
145
  body_root.pack_same_size
@@ -152,56 +151,61 @@ module Glimmer
152
151
  @current_tab_item = found_tab_item.getData('proxy')
153
152
  @current_text_editor = found_tab_item.getData('text_editor') unless found_tab_item.getData('text_editor').nil?
154
153
  @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
155
- elsif selected_file
156
- @current_tab_folder.content {
157
- @current_tab_item = tab_item { |the_tab_item|
158
- text selected_file.name
159
- fill_layout(:horizontal) {
160
- margin_width 0
161
- margin_height 0
162
- }
163
- tab_folder = nil
164
- the_text_editor = nil
165
- the_tab_item.content {
166
- @current_text_editor = the_text_editor = text_editor(project_dir: project_dir, file: selected_file) {
167
- layout_data :fill, :fill, true, true
154
+ else
155
+ begin
156
+ @current_tab_folder.content {
157
+ @current_tab_item = tab_item { |the_tab_item|
158
+ text selected_file.name
159
+ fill_layout(:horizontal) {
160
+ margin_width 0
161
+ margin_height 0
168
162
  }
169
- @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
170
- the_tab_item.swt_tab_item.setData('text_editor', @current_text_editor)
171
- @current_text_editor.text_proxy.content {
172
- on_focus_gained {
173
- tab_folder = the_text_editor.swt_widget.getParent.getParent
174
- self.current_tab_folder = tab_folder.getData('proxy')
175
- @current_tab_item = the_tab_item
176
- @current_text_editor = the_text_editor
177
- @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
178
- @current_tab_folder.swt_widget.setSelection(@current_tab_item.swt_tab_item)
179
- project_dir.selected_child = @current_tab_item.swt_tab_item.getData('file')
163
+ tab_folder = nil
164
+ the_text_editor = nil
165
+ the_tab_item.content {
166
+ @current_text_editor = the_text_editor = text_editor(project_dir: project_dir, file: selected_file) {
167
+ layout_data :fill, :fill, true, true
168
+ }
169
+ @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
170
+ the_tab_item.swt_tab_item.setData('text_editor', @current_text_editor)
171
+ @current_text_editor.text_proxy.content {
172
+ on_focus_gained {
173
+ tab_folder = the_text_editor.swt_widget.getParent.getParent
174
+ self.current_tab_folder = tab_folder.getData('proxy')
175
+ @current_tab_item = the_tab_item
176
+ @current_text_editor = the_text_editor
177
+ @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
178
+ @current_tab_folder.swt_widget.setSelection(@current_tab_item.swt_tab_item)
179
+ project_dir.selected_child = @current_tab_item.swt_tab_item.getData('file')
180
+ }
180
181
  }
181
182
  }
183
+ on_swt_show {
184
+ @current_tab_item = the_tab_item
185
+ @current_text_editor = the_text_editor
186
+ self.current_tab_folder = @current_tab_item.swt_widget.getParent.getData('proxy')
187
+ @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
188
+ @current_tab_folder.swt_widget.setSelection(@current_tab_item.swt_tab_item)
189
+ project_dir.selected_child = selected_file
190
+ @current_text_editor&.load_content
191
+ @current_text_editor&.text_widget&.setFocus
192
+ save_config unless selected_file.nil?
193
+ }
194
+ on_widget_disposed {
195
+ project_dir.selected_child&.write_dirty_content
196
+ tab_item_file = the_tab_item.swt_tab_item.get_data('file')
197
+ tab_item_file.close unless [@tab_folder1, @tab_folder2].compact.map(&:items).flatten(1).detect {|ti| ti.get_data('file') == tab_item_file}
198
+ }
182
199
  }
183
-
184
- on_swt_show {
185
- @current_tab_item = the_tab_item
186
- @current_text_editor = the_text_editor
187
- self.current_tab_folder = @current_tab_item.swt_widget.getParent.getData('proxy')
188
- @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item)
189
- @current_tab_folder.swt_widget.setSelection(@current_tab_item.swt_tab_item)
190
- project_dir.selected_child = selected_file
191
- @current_text_editor&.text_widget&.setFocus
192
- }
193
- on_widget_disposed {
194
- project_dir.selected_child&.write_dirty_content
195
- tab_item_file = the_tab_item.swt_tab_item.get_data('file')
196
- tab_item_file.close unless [@tab_folder1, @tab_folder2].compact.map(&:items).flatten(1).detect {|ti| ti.get_data('file') == tab_item_file}
197
- }
200
+ @current_tab_item.swt_tab_item.setData('file_path', selected_file.path)
201
+ @current_tab_item.swt_tab_item.setData('file', selected_file)
202
+ @current_tab_item.swt_tab_item.setData('proxy', @current_tab_item)
198
203
  }
199
- @current_tab_item.swt_tab_item.setData('file_path', selected_file.path)
200
- @current_tab_item.swt_tab_item.setData('file', selected_file)
201
- @current_tab_item.swt_tab_item.setData('proxy', @current_tab_item)
202
- }
203
- @current_tab_folder.swt_widget.setSelection(@current_tab_item.swt_tab_item)
204
- body_root.pack_same_size
204
+ @current_tab_folder.swt_widget.setSelection(@current_tab_item.swt_tab_item)
205
+ body_root.pack_same_size
206
+ rescue => e
207
+ puts e.full_message
208
+ end
205
209
  end
206
210
  @current_text_editor&.text_widget&.setFocus
207
211
  end
@@ -266,7 +270,6 @@ module Glimmer
266
270
  }
267
271
 
268
272
  on_shell_closed {
269
- save_config
270
273
  project_dir.selected_child&.write_dirty_content
271
274
  if @tab_folder2
272
275
  current_tab_folder.swt_widget.getItems.each do |tab_item|
@@ -644,28 +647,44 @@ module Glimmer
644
647
  minimum_height 176
645
648
  }
646
649
  orientation bind(self, :split_orientation) {|value| async_exec { body_root.pack_same_size}; value}
647
- self.current_tab_folder = self.tab_folder1 = tab_folder {
648
- drag_source(DND::DROP_COPY) {
649
- transfer [TextTransfer.getInstance].to_java(Transfer)
650
- event_data = nil
651
- on_drag_start {|event|
652
- Gladiator.drag = true
653
- tab_folder = event.widget.getControl
654
- tab_item = tab_folder.getItem(Point.new(event.x, event.y))
655
- event_data = tab_item.getData('file_path')
656
- }
657
- on_drag_set_data { |event|
658
- event.data = event_data
659
- }
660
- }
661
- }
662
- @current_tab_folder.swt_widget.setData('proxy', @current_tab_folder)
650
+ self.current_tab_folder = self.tab_folder1 = text_editor_group_tab_folder
651
+ @current_tab_folder.swt_widget.setData('proxy', @current_tab_folder) # TODO see if we could get rid of this as it seems redundant
663
652
  }
664
653
  }
665
654
  } # end of sash form
666
655
  }
667
656
  end
668
657
  }
658
+
659
+ def text_editor_group_tab_folder
660
+ tab_folder { |tab_folder_proxy|
661
+ on_widget_selected {
662
+ self.current_tab_folder = tab_folder_proxy
663
+ selected_file = @current_tab_item&.swt_tab_item&.getData('file')
664
+ if selected_file
665
+ project_dir.selected_child = selected_file
666
+ @current_tab_item = @current_tab_folder.swt_widget.getSelection.first.getData('proxy')
667
+ @current_tab_folder.swt_widget.setData('selected_tab_item', @current_tab_item) #TODO see if we can get rid of this as it seems redundant
668
+ @current_text_editor = @current_tab_item.swt_tab_item.getData('text_editor')
669
+ @current_text_editor&.load_content
670
+ @current_text_editor&.text_widget&.setFocus
671
+ end
672
+ }
673
+ drag_source(DND::DROP_COPY) {
674
+ transfer [TextTransfer.getInstance].to_java(Transfer)
675
+ event_data = nil
676
+ on_drag_start {|event|
677
+ Gladiator.drag = true
678
+ tab_folder = event.widget.getControl
679
+ tab_item = tab_folder.getItem(Point.new(event.x, event.y))
680
+ event_data = tab_item.getData('file_path')
681
+ }
682
+ on_drag_set_data { |event|
683
+ event.data = event_data
684
+ }
685
+ }
686
+ }
687
+ end
669
688
 
670
689
  def load_config_ignore_paths
671
690
  # TODO eliminate duplication with load_config
@@ -759,11 +778,11 @@ module Glimmer
759
778
  return if child.nil?
760
779
  tab_folder1 = @tab_folder1 || @current_tab_folder
761
780
  tab_folder2 = @tab_folder2
762
- open_file_paths1 = tab_folder1&.swt_widget&.items.to_a.map {|i| i.get_data('file_path')}
763
- open_file_paths2 = tab_folder2&.swt_widget&.items.to_a.map {|i| i.get_data('file_path')}
781
+ open_file_paths1 = tab_folder1&.swt_widget&.items.to_a.map {|i| i.get_data('file_path')}.reject {|path| path.to_s.strip.empty?}
782
+ open_file_paths2 = tab_folder2&.swt_widget&.items.to_a.map {|i| i.get_data('file_path')}.reject {|path| path.to_s.strip.empty?}
764
783
  split_orientation_value = split_orientation == swt(:horizontal) ? 'horizontal' : (split_orientation == swt(:vertical) ? 'vertical' : nil)
765
784
  @config = {
766
- selected_child_path: child.path,
785
+ selected_child_path: child.nil? ? open_file_paths1&.first&.path : child.path,
767
786
  split_orientation: split_orientation_value,
768
787
  caret_position: child.caret_position,
769
788
  top_pixel: child.top_pixel,
@@ -966,16 +985,18 @@ module Glimmer
966
985
  # async_exec { current_text_editor&.text_widget&.setFocus }
967
986
  end
968
987
  end
969
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == ']'
988
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == ']' || Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :ctrl) && key_event.keyCode == swt(:page_down)
970
989
  current_tab_folder.swt_widget.setSelection((current_tab_folder.swt_widget.getSelectionIndex() + 1) % current_tab_folder.swt_widget.getItemCount) if current_tab_folder.swt_widget.getItemCount > 0
971
990
  current_text_editor&.text_widget&.setFocus
972
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == '['
991
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == '[' || Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :ctrl) && key_event.keyCode == swt(:page_up)
973
992
  current_tab_folder.swt_widget.setSelection((current_tab_folder.swt_widget.getSelectionIndex() - 1) % current_tab_folder.swt_widget.getItemCount) if current_tab_folder.swt_widget.getItemCount > 0
974
993
  current_text_editor&.text_widget&.setFocus
975
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :ctrl) && extract_char(key_event) == ']'
994
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, CONTROL_KEY) && extract_char(key_event) == ']'
976
995
  navigate_to_next_tab_folder
977
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :ctrl) && extract_char(key_event) == '['
996
+ key_event.doit = false
997
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, CONTROL_KEY) && extract_char(key_event) == '['
978
998
  navigate_to_previous_tab_folder
999
+ key_event.doit = false
979
1000
  elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '1'
980
1001
  current_tab_folder.swt_widget.setSelection(0) if current_tab_folder.swt_widget.getItemCount >= 1
981
1002
  current_text_editor&.text_widget&.setFocus
@@ -1,244 +1,244 @@
1
- # Copyright (c) 2020-2021 Andy Maleh
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining
4
- # a copy of this software and associated documentation files (the
5
- # "Software"), to deal in the Software without restriction, including
6
- # without limitation the rights to use, copy, modify, merge, publish,
7
- # distribute, sublicense, and/or sell copies of the Software, and to
8
- # permit persons to whom the Software is furnished to do so, subject to
9
- # the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be
12
- # included in all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
- module Glimmer
23
- class Gladiator
24
- class FileExplorerTree
25
- include Glimmer::UI::CustomWidget
26
-
27
- options :gladiator, :foreground_color
28
-
29
- body {
30
- tree {
31
- #visible bind(self, 'project_dir.filter') {|f| !f}
32
- items bind(self, :project_dir), tree_properties(children: :children, text: :name)
33
- foreground foreground_color
34
- drag_source(:drop_copy) {
35
- transfer :text
36
- on_drag_set_data { |event|
37
- Gladiator.drag = true
38
- tree = event.widget.getControl
39
- tree_item = tree.getSelection.first
40
- event.data = tree_item.getData.path
41
- }
42
- }
43
-
44
- menu {
45
- @open_menu_item = menu_item {
46
- text 'Open'
47
- on_widget_selected {
48
- project_dir.selected_child_path = extract_tree_item_path(swt_widget.getSelection.first)
49
- }
50
- }
51
- menu_item(:separator)
52
- menu_item {
53
- text 'Delete'
54
- on_widget_selected {
55
- tree_item = swt_widget.getSelection.first
56
- delete_tree_item(tree_item)
57
- }
58
- }
59
- menu_item {
60
- text 'Refresh'
61
- on_widget_selected {
62
- project_dir.refresh
63
- }
64
- }
65
- menu_item {
66
- text 'Rename'
67
- on_widget_selected {
68
- rename_selected_tree_item
69
- }
70
- }
71
- menu_item {
72
- text 'New Directory'
73
- on_widget_selected {
74
- add_new_directory_to_selected_tree_item
75
- }
76
- }
77
- menu_item {
78
- text 'New File'
79
- on_widget_selected {
80
- add_new_file_to_selected_tree_item
81
- }
82
- }
83
- }
84
-
85
- on_swt_menudetect { |event|
86
- path = extract_tree_item_path(swt_widget.getSelection.first)
87
- @open_menu_item.swt_widget.setEnabled(!::Dir.exist?(path)) if path
88
- }
89
- on_mouse_up {
90
- if Gladiator.drag_and_drop
91
- Gladiator.drag_and_drop = false
92
- else
93
- project_dir.selected_child_path = extract_tree_item_path(swt_widget.getSelection&.first)
94
- gladiator.current_text_editor&.text_widget&.setFocus
95
- end
96
- }
97
- on_key_pressed { |key_event|
98
- if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr)
99
- project_dir.selected_child_path = extract_tree_item_path(swt_widget.getSelection&.first)
100
- gladiator.current_text_editor&.text_widget&.setFocus
101
- end
102
- }
103
- on_paint_control {
104
- root_item = swt_widget.getItems.first
105
- if root_item && !root_item.getExpanded
106
- root_item.setExpanded(true)
107
- end
108
- }
109
-
110
- }
111
- }
112
-
113
- def project_dir
114
- gladiator.project_dir
115
- end
116
-
117
- def current_text_editor
118
- gladiator.current_text_editor
119
- end
120
-
121
- def extract_tree_item_path(tree_item)
122
- return if tree_item.nil?
123
- if tree_item.getParentItem
124
- ::File.join(extract_tree_item_path(tree_item.getParentItem), tree_item.getText)
125
- else
126
- project_dir.path
127
- end
128
- end
129
-
130
- def select_tree_item
131
- return unless project_dir.selected_child&.name
132
- tree_items_to_select = body_root.depth_first_search { |ti| ti.getData.path == project_dir.selected_child.path }
133
- swt_widget.setSelection(tree_items_to_select)
134
- end
135
-
136
- def delete_tree_item(tree_item)
137
- return if tree_item.nil?
138
- file = tree_item.getData
139
- parent_path = ::File.dirname(file.path)
140
- if file.is_a?(Gladiator::Dir)
141
- file_paths = file.all_children.select {|f| f.is_a?(Gladiator::File)}.map(&:path)
142
- file.remove_all_observers
143
- else
144
- file_paths = [file.path]
145
- end
146
- file_paths.each do |file_path|
147
- found_tab_item = gladiator.find_tab_item(file_path)
148
- if found_tab_item
149
- project_dir.selected_child_path_history.delete(found_tab_item.getData('file_path'))
150
- found_tab_item.getData('proxy')&.dispose
151
- end
152
- end
153
- file.delete! # TODO consider supporting command undo/redo
154
- project_dir.refresh(async: false)
155
- parent_tree_item = body_root.depth_first_search {|ti| ti.getData.path == parent_path}.first
156
- swt_widget.showItem(parent_tree_item)
157
- parent_tree_item.setExpanded(true)
158
- rescue => e
159
- puts e.full_message
160
- end
161
-
162
- def add_new_directory_to_selected_tree_item
163
- project_dir.pause_refresh
164
- tree_item = swt_widget.getSelection.first
165
- directory_path = extract_tree_item_path(tree_item)
166
- return if directory_path.nil?
167
- if !::Dir.exist?(directory_path)
168
- tree_item = tree_item.getParentItem
169
- directory_path = ::File.dirname(directory_path)
170
- end
171
- new_directory_path = ::File.expand_path(::File.join(directory_path, 'new_directory'))
172
- FileUtils.mkdir_p(new_directory_path)
173
- project_dir.refresh(async: false, force: true)
174
- new_tree_item = body_root.depth_first_search {|ti| ti.getData.path == new_directory_path}.first
175
- swt_widget.showItem(new_tree_item)
176
- rename_tree_item(new_tree_item)
177
- end
178
-
179
- def add_new_file_to_selected_tree_item
180
- project_dir.pause_refresh
181
- tree_item = swt_widget.getSelection.first
182
- directory_path = extract_tree_item_path(tree_item)
183
- if !::Dir.exist?(directory_path)
184
- tree_item = tree_item.getParentItem
185
- directory_path = ::File.dirname(directory_path)
186
- end
187
- new_file_path = ::File.expand_path(::File.join(directory_path, 'new_file'))
188
- FileUtils.touch(new_file_path)
189
- # TODO look into refreshing only the parent directory to avoid slowdown
190
- project_dir.refresh(async: false, force: true)
191
- new_tree_item = body_root.depth_first_search {|ti| ti.getData.path == new_file_path}.first
192
- swt_widget.showItem(new_tree_item)
193
- rename_tree_item(new_tree_item, true)
194
- end
195
-
196
- def rename_selected_tree_item
197
- project_dir.pause_refresh
198
- tree_item = swt_widget.getSelection.first
199
- rename_tree_item(tree_item)
200
- end
201
-
202
- def rename_tree_item(tree_item, new_file = false)
203
- original_file = tree_item.getData
204
- current_file = project_dir.selected_child_path == original_file.path
205
- found_tab_item = gladiator.find_tab_item(original_file.path)
206
- found_text_editor = found_tab_item&.getData('text_editor')
207
- body_root.edit_tree_item(
208
- tree_item,
209
- after_write: -> (edited_tree_item) {
210
- file = edited_tree_item.getData
211
- file_path = file.path
212
- file.name
213
- if ::File.file?(file_path)
214
- if new_file
215
- project_dir.selected_child_path = file_path
216
- else
217
- found_text_editor&.file = file
218
- found_tab_item&.setData('file', file)
219
- found_tab_item&.setData('file_path', file.path)
220
- found_tab_item&.setText(file.name)
221
- body_root.pack_same_size
222
- if current_file
223
- project_dir.selected_child_path = file_path
224
- else
225
- selected_tab_item&.getData('text_editor')&.text_widget&.setFocus
226
- end
227
- async_exec {
228
- swt_widget.showItem(edited_tree_item)
229
- }
230
- end
231
- end
232
- project_dir.resume_refresh
233
- },
234
- after_cancel: -> {
235
- project_dir.resume_refresh
236
- }
237
- )
238
- end
239
-
240
- end
241
-
242
- end
243
-
244
- end
1
+ # Copyright (c) 2020-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module Glimmer
23
+ class Gladiator
24
+ class FileExplorerTree
25
+ include Glimmer::UI::CustomWidget
26
+
27
+ options :gladiator, :foreground_color
28
+
29
+ body {
30
+ tree {
31
+ #visible bind(self, 'project_dir.filter') {|f| !f}
32
+ items bind(self, :project_dir), tree_properties(children: :children, text: :name)
33
+ foreground foreground_color
34
+ drag_source(:drop_copy) {
35
+ transfer :text
36
+ on_drag_set_data { |event|
37
+ Gladiator.drag = true
38
+ tree = event.widget.getControl
39
+ tree_item = tree.getSelection.first
40
+ event.data = tree_item.getData.path
41
+ }
42
+ }
43
+
44
+ menu {
45
+ @open_menu_item = menu_item {
46
+ text 'Open'
47
+ on_widget_selected {
48
+ project_dir.selected_child_path = extract_tree_item_path(swt_widget.getSelection.first)
49
+ }
50
+ }
51
+ menu_item(:separator)
52
+ menu_item {
53
+ text 'Delete'
54
+ on_widget_selected {
55
+ tree_item = swt_widget.getSelection.first
56
+ delete_tree_item(tree_item)
57
+ }
58
+ }
59
+ menu_item {
60
+ text 'Refresh'
61
+ on_widget_selected {
62
+ project_dir.refresh
63
+ }
64
+ }
65
+ menu_item {
66
+ text 'Rename'
67
+ on_widget_selected {
68
+ rename_selected_tree_item
69
+ }
70
+ }
71
+ menu_item {
72
+ text 'New Directory'
73
+ on_widget_selected {
74
+ add_new_directory_to_selected_tree_item
75
+ }
76
+ }
77
+ menu_item {
78
+ text 'New File'
79
+ on_widget_selected {
80
+ add_new_file_to_selected_tree_item
81
+ }
82
+ }
83
+ }
84
+
85
+ on_swt_menudetect { |event|
86
+ path = extract_tree_item_path(swt_widget.getSelection.first)
87
+ @open_menu_item.swt_widget.setEnabled(!::Dir.exist?(path)) if path
88
+ }
89
+ on_mouse_up {
90
+ if Gladiator.drag_and_drop
91
+ Gladiator.drag_and_drop = false
92
+ else
93
+ project_dir.selected_child_path = extract_tree_item_path(swt_widget.getSelection&.first)
94
+ gladiator.current_text_editor&.text_widget&.setFocus
95
+ end
96
+ }
97
+ on_key_pressed { |key_event|
98
+ if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr)
99
+ project_dir.selected_child_path = extract_tree_item_path(swt_widget.getSelection&.first)
100
+ gladiator.current_text_editor&.text_widget&.setFocus
101
+ end
102
+ }
103
+ on_paint_control {
104
+ root_item = swt_widget.getItems.first
105
+ if root_item && !root_item.getExpanded
106
+ root_item.setExpanded(true)
107
+ end
108
+ }
109
+
110
+ }
111
+ }
112
+
113
+ def project_dir
114
+ gladiator.project_dir
115
+ end
116
+
117
+ def current_text_editor
118
+ gladiator.current_text_editor
119
+ end
120
+
121
+ def extract_tree_item_path(tree_item)
122
+ return if tree_item.nil?
123
+ if tree_item.getParentItem
124
+ ::File.join(extract_tree_item_path(tree_item.getParentItem), tree_item.getText)
125
+ else
126
+ project_dir.path
127
+ end
128
+ end
129
+
130
+ def select_tree_item
131
+ return unless project_dir.selected_child&.name
132
+ tree_items_to_select = body_root.depth_first_search { |ti| ti.getData.path == project_dir.selected_child.path }
133
+ swt_widget.setSelection(tree_items_to_select)
134
+ end
135
+
136
+ def delete_tree_item(tree_item)
137
+ return if tree_item.nil?
138
+ file = tree_item.getData
139
+ parent_path = ::File.dirname(file.path)
140
+ if file.is_a?(Gladiator::Dir)
141
+ file_paths = file.all_children.select {|f| f.is_a?(Gladiator::File)}.map(&:path)
142
+ file.remove_all_observers
143
+ else
144
+ file_paths = [file.path]
145
+ end
146
+ file_paths.each do |file_path|
147
+ found_tab_item = gladiator.find_tab_item(file_path)
148
+ if found_tab_item
149
+ project_dir.selected_child_path_history.delete(found_tab_item.getData('file_path'))
150
+ found_tab_item.getData('proxy')&.dispose
151
+ end
152
+ end
153
+ file.delete! # TODO consider supporting command undo/redo
154
+ project_dir.refresh(async: false)
155
+ parent_tree_item = body_root.depth_first_search {|ti| ti.getData.path == parent_path}.first
156
+ swt_widget.showItem(parent_tree_item)
157
+ parent_tree_item.setExpanded(true)
158
+ rescue => e
159
+ puts e.full_message
160
+ end
161
+
162
+ def add_new_directory_to_selected_tree_item
163
+ project_dir.pause_refresh
164
+ tree_item = swt_widget.getSelection.first
165
+ directory_path = extract_tree_item_path(tree_item)
166
+ return if directory_path.nil?
167
+ if !::Dir.exist?(directory_path)
168
+ tree_item = tree_item.getParentItem
169
+ directory_path = ::File.dirname(directory_path)
170
+ end
171
+ new_directory_path = ::File.expand_path(::File.join(directory_path, 'new_directory'))
172
+ FileUtils.mkdir_p(new_directory_path)
173
+ project_dir.refresh(async: false, force: true)
174
+ new_tree_item = body_root.depth_first_search {|ti| ti.getData.path == new_directory_path}.first
175
+ swt_widget.showItem(new_tree_item)
176
+ rename_tree_item(new_tree_item)
177
+ end
178
+
179
+ def add_new_file_to_selected_tree_item
180
+ project_dir.pause_refresh
181
+ tree_item = swt_widget.getSelection.first
182
+ directory_path = extract_tree_item_path(tree_item)
183
+ if !::Dir.exist?(directory_path)
184
+ tree_item = tree_item.getParentItem
185
+ directory_path = ::File.dirname(directory_path)
186
+ end
187
+ new_file_path = ::File.expand_path(::File.join(directory_path, 'new_file'))
188
+ FileUtils.touch(new_file_path)
189
+ # TODO look into refreshing only the parent directory to avoid slowdown
190
+ project_dir.refresh(async: false, force: true)
191
+ new_tree_item = body_root.depth_first_search {|ti| ti.getData.path == new_file_path}.first
192
+ swt_widget.showItem(new_tree_item)
193
+ rename_tree_item(new_tree_item, true)
194
+ end
195
+
196
+ def rename_selected_tree_item
197
+ project_dir.pause_refresh
198
+ tree_item = swt_widget.getSelection.first
199
+ rename_tree_item(tree_item)
200
+ end
201
+
202
+ def rename_tree_item(tree_item, new_file = false)
203
+ original_file = tree_item.getData
204
+ current_file = project_dir.selected_child_path == original_file.path
205
+ found_tab_item = gladiator.find_tab_item(original_file.path)
206
+ found_text_editor = found_tab_item&.getData('text_editor')
207
+ body_root.edit_tree_item(
208
+ tree_item,
209
+ after_write: -> (edited_tree_item) {
210
+ file = edited_tree_item.getData
211
+ file_path = file.path
212
+ file.name
213
+ if ::File.file?(file_path)
214
+ if new_file
215
+ project_dir.selected_child_path = file_path
216
+ else
217
+ found_text_editor&.file = file
218
+ found_tab_item&.setData('file', file)
219
+ found_tab_item&.setData('file_path', file.path)
220
+ found_tab_item&.setText(file.name)
221
+ body_root.pack_same_size
222
+ if current_file
223
+ project_dir.selected_child_path = file_path
224
+ else
225
+ selected_tab_item&.getData('text_editor')&.text_widget&.setFocus
226
+ end
227
+ async_exec {
228
+ swt_widget.showItem(edited_tree_item)
229
+ }
230
+ end
231
+ end
232
+ project_dir.resume_refresh
233
+ },
234
+ after_cancel: -> {
235
+ project_dir.resume_refresh
236
+ }
237
+ )
238
+ end
239
+
240
+ end
241
+
242
+ end
243
+
244
+ end