gvcsfx 0.3

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.
@@ -0,0 +1,224 @@
1
+ # Copyright (C) 2020 Chris Liaw <chrisliaw@antrapol.com>
2
+ # Author: Chris Liaw <chrisliaw@antrapol.com>
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+
18
+
19
+ module GvcsFx
20
+ module TabTags
21
+
22
+ class VCSTag
23
+ include Antrapol::ToolRack::ExceptionUtils
24
+ attr_accessor :key, :name, :date, :author, :subject
25
+ def formatted_date
26
+ if not_empty?(@date)
27
+ dt = rdate
28
+ dt.strftime("%d.%b.%Y (%a) %H:%M %z")
29
+ else
30
+ ""
31
+ end
32
+ end
33
+
34
+ # for sorting
35
+ def rdate
36
+ DateTime.strptime(@date,"%a %b %d %H:%M:%S %Y %z")
37
+ end
38
+
39
+ def to_s
40
+ "#{@name} [#{formatted_date} by #{@author}]"
41
+ end
42
+ end
43
+
44
+ def init_tab_tags
45
+
46
+ @lstTags.selection_model.selection_mode = javafx.scene.control.SelectionMode::SINGLE
47
+
48
+ @lstTags.add_event_handler(javafx.scene.input.MouseEvent::MOUSE_CLICKED, Proc.new do |evt|
49
+ if evt.button == javafx.scene.input.MouseButton::SECONDARY
50
+ # # right click on item
51
+ tags_ctxmenu.show(@lstTags, evt.screen_x, evt.screen_y)
52
+ elsif evt.button == javafx.scene.input.MouseButton::PRIMARY and evt.click_count == 2
53
+ # double click on item - view file
54
+ sel = @lstTags.selection_model.selected_items
55
+ if sel.length > 0
56
+ s = sel.first
57
+ st, res = @selWs.show_tag_detail(s.name)
58
+ if st
59
+ show_content_win("Tag Detail","Tag Detail", res)
60
+ else
61
+ prompt_error("Failed to load tag detail for tag '#{s}'. Error was : #{res}")
62
+ end
63
+ end
64
+
65
+ end
66
+ end)
67
+
68
+ end
69
+
70
+ def refresh_tab_tags
71
+
72
+ @lstTags.items.clear
73
+
74
+ dat = []
75
+ st, res = @selWs.all_tags
76
+ if st and not_empty?(res)
77
+
78
+ res.each_line do |e|
79
+
80
+ st2,res2 = @selWs.tag_info(e.strip)
81
+ if st2
82
+
83
+ res2.each_line do |r|
84
+ rr = r.split("|")
85
+ # extremely unreliable that depending on default
86
+ # format in tag_info
87
+ if rr.length == 4
88
+ @rec = rr
89
+ break
90
+ else
91
+ next
92
+ end
93
+ end
94
+
95
+ # default format = %H|%ad|%an|%s
96
+ if not_empty?(@rec)
97
+ vt = VCSTag.new
98
+ vt.name = e.strip
99
+ vt.key = @rec[0]
100
+ vt.date = @rec[1]
101
+ vt.author = @rec[2]
102
+ vt.subject = @rec[3]
103
+ #vt.name = e[0]
104
+ #vt.date = e[1]
105
+ #vt.author = e[2]
106
+ #vt.subject = e[3]
107
+ dat << vt
108
+ end
109
+ end
110
+
111
+ end # tag info line
112
+
113
+ # sort
114
+ dat = dat.sort do |a,b|
115
+ # oldest comes to the top
116
+ #a.rdate <=> b.rdate
117
+ # latest comes to the top
118
+ b.rdate <=> a.rdate
119
+ #case
120
+ #when a.rdate < b.rdate
121
+ # 1
122
+ #when a.rdate > b.rdate
123
+ # -1
124
+ #else
125
+ # a.rdate <=> b.rdate
126
+ #end
127
+ end
128
+
129
+ @lstTags.items.add_all(dat)
130
+ end
131
+
132
+ @txtNewTagName.clear
133
+ @txtNewTagNote.clear
134
+
135
+ end # refresh_tab_tags
136
+
137
+ def create_tag(evt)
138
+ tn = @txtNewTagName.text
139
+ if is_empty?(tn)
140
+ fx_alert_error("Tag name cannot be empty","Empty Tag Name", main_stage)
141
+ else
142
+ msg = @txtNewTagNote.text
143
+ tn = tn.gsub(" ","-")
144
+ st, res = @selWs.create_tag(tn,msg)
145
+ if st
146
+ set_success_gmsg("New tag '#{tn}' successfully created.")
147
+ refresh_tab_tags
148
+ else
149
+ prompt_error(res.strip, "New Tag Creation Failed", main_stage)
150
+ end
151
+ end
152
+ end # create_tag
153
+
154
+ def new_tag_keypressed(evt)
155
+ if evt.code == javafx.scene.input.KeyCode::ENTER
156
+ create_tag(nil)
157
+ end
158
+ end
159
+
160
+ def lstTags_keypressed(evt)
161
+ if evt.code == javafx.scene.input.KeyCode::DELETE
162
+ selTag = @lstTags.selection_model.selected_item
163
+ if not selTag.nil?
164
+ res = fx_alert_confirmation("Remove tag '#{selTag.name}'?", nil, "Confirmation to Remove Tag", main_stage)
165
+ if res == :ok
166
+ st, res = @selWs.delete_tag(selTag.name)
167
+
168
+ if st
169
+ set_success_gmsg("Tag '#{selTag.name}' successfully deleted.")
170
+ refresh_tab_tags
171
+ else
172
+ prompt_error("Failed to delete tag '#{selTag.name}'. Error was : #{res}")
173
+ end
174
+
175
+ end
176
+ end
177
+ end
178
+ #@selTag = @lstTags.selection_model.selected_item
179
+ end
180
+
181
+ def tagnote_keypressed(evt)
182
+ if evt.code == javafx.scene.input.KeyCode::ENTER
183
+ create_tag(nil)
184
+ end
185
+ end
186
+
187
+ def tags_ctxmenu
188
+
189
+ selTag = @lstTags.selection_model.selected_item
190
+
191
+ tagsCtxMenu = javafx.scene.control.ContextMenu.new
192
+
193
+ if not_empty?(selTag)
194
+
195
+ coMnuItm = javafx.scene.control.MenuItem.new("Checkout to new branch")
196
+ coMnuItm.on_action do |evt|
197
+
198
+ st, name = fx_alert_input("Check out to a branch","Check out tag '#{selTag.name}' into new branch", "New Branch Name *")
199
+ if st
200
+ if not_empty?(name)
201
+ sst, res = @selWs.checkout_tag(selTag.name, name)
202
+ if sst
203
+ set_success_gmsg(res)
204
+ refresh_tab_tags
205
+ else
206
+ prompt_error("Failed to checkout tag '#{selTag.name}' to new branch '#{name}'. Error was : #{res}")
207
+ end
208
+ else
209
+ prompt_error("Please provide a branch name")
210
+ end
211
+ end
212
+
213
+ end # on_action do .. end
214
+
215
+ tagsCtxMenu.items.add(coMnuItm)
216
+
217
+ end
218
+
219
+ tagsCtxMenu
220
+
221
+ end
222
+
223
+ end
224
+ end
@@ -0,0 +1,128 @@
1
+ # Copyright (C) 2020 Chris Liaw <chrisliaw@antrapol.com>
2
+ # Author: Chris Liaw <chrisliaw@antrapol.com>
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+
18
+ java_import java.awt.AWTException
19
+ java_import java.awt.Menu
20
+ java_import java.awt.MenuItem
21
+ java_import java.awt.PopupMenu
22
+ java_import java.awt.SystemTray
23
+ java_import java.awt.TrayIcon
24
+ java_import java.awt.event.ActionEvent
25
+ java_import java.awt.event.ActionListener
26
+ java_import javax.swing.ImageIcon
27
+ java_import javax.swing.JOptionPane
28
+
29
+ java_import javax.swing.JPopupMenu
30
+ java_import javax.swing.JMenu
31
+ java_import javax.swing.JMenuItem
32
+
33
+ require_relative "../lib/global"
34
+ require_relative '../lib/log_helper'
35
+
36
+ module GvcsFx
37
+ module Tray
38
+ include GvcsFx::LogHelper
39
+
40
+ def start_tray(app = nil)
41
+
42
+ if SystemTray.isSupported
43
+
44
+ begin
45
+
46
+ Java::JavaxSwing::UIManager.setLookAndFeel(Java::JavaxSwing::UIManager.getSystemLookAndFeelClassName())
47
+
48
+ tray = SystemTray.getSystemTray
49
+ popup = JPopupMenu.new
50
+ if inside_jar?
51
+ icon = TrayIcon.new(java.awt.Toolkit::default_toolkit.get_image(java.lang.Object.new.java_class.resource("/gvcs_fx/res/version-control.png")),"G-VCS")
52
+ else
53
+ icon = TrayIcon.new(ImageIcon.new(File.join(File.dirname(__FILE__),"..","res","version-control.png")).getImage,"G-VCS")
54
+ end
55
+
56
+ mainAct = JMenuItem.new("G-VCS")
57
+ mainAct.add_action_listener do |evt|
58
+
59
+ #javafx.application.Platform.run_later do
60
+ #puts "Inside run later!"
61
+ #begin
62
+ # app.show_stage
63
+ #rescue Exception => ex
64
+ # puts ex
65
+ # #log_error(ex.message)
66
+ #end
67
+ #end
68
+ #puts "after run_later"
69
+ end
70
+ popup.add(mainAct)
71
+
72
+ popup.addSeparator
73
+
74
+ aboutItm = JMenuItem.new("About")
75
+ aboutItm.add_action_listener do |evt|
76
+ end
77
+ popup.add(aboutItm)
78
+
79
+ exitItm = JMenuItem.new("Exit")
80
+ exitItm.add_action_listener do |evt|
81
+ ans = JOptionPane::showConfirmDialog(nil,"Exit G-VCS?","Exit Confirmation",JOptionPane::YES_NO_OPTION,JOptionPane::QUESTION_MESSAGE)
82
+ if ans == JOptionPane::YES_OPTION
83
+
84
+ javafx.application.Platform.exit
85
+
86
+ SystemTray.getSystemTray.remove(icon)
87
+ java.lang.System.exit(0)
88
+ end
89
+ end
90
+ popup.add(exitItm)
91
+
92
+ # if using this approach the pop up menu will not OS native look...
93
+ #icon.setPopupMenu(popup)
94
+ # https://stackoverflow.com/a/17258735
95
+ icon.add_mouse_listener do |evt|
96
+ if (evt.getID == java.awt.event.MouseEvent::MOUSE_CLICKED)
97
+ # isPopupTrigger is recommended if the moust event is mousePressed
98
+ #if evt.isPopupTrigger
99
+ popup.setLocation(evt.getX(),evt.getY())
100
+ popup.setInvoker(popup)
101
+ popup.visible = true
102
+ #end
103
+ end
104
+ end
105
+
106
+ icon.setImageAutoSize(true)
107
+ tray.add(icon)
108
+
109
+ rescue Exception => ex
110
+ STDERR.puts ex.backtrace.join("\n")
111
+ #log_error(ex.message)
112
+ #fx_alert_error ex.message, "G-VCS Tray Startup Exception"
113
+ end
114
+
115
+ else
116
+ Global.instance.debug "No tray support"
117
+ #fx_alert_error("No tray support for this platform")
118
+ end
119
+
120
+ end # show_tray
121
+
122
+ def inside_jar?
123
+ File.dirname(__FILE__)[0..3] == "uri:"
124
+ end
125
+
126
+
127
+ end # module Tray
128
+ end
@@ -0,0 +1,547 @@
1
+ # Copyright (C) 2020 Chris Liaw <chrisliaw@antrapol.com>
2
+ # Author: Chris Liaw <chrisliaw@antrapol.com>
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+
18
+ require_relative '../lib/store'
19
+
20
+ java_import javafx.scene.control.cell.PropertyValueFactory
21
+ java_import javafx.scene.control.TreeTableColumn
22
+ java_import javafx.collections.FXCollections
23
+ java_import javafx.beans.property.SimpleStringProperty
24
+ java_import javafx.scene.control.TreeItem
25
+ java_import javafx.scene.text.Text
26
+ java_import javafx.application.Platform
27
+
28
+ module GvcsFx
29
+ module Workspace
30
+
31
+ class TreeWorkspace
32
+ include javafx.beans.value.ObservableValue
33
+
34
+ attr_accessor :project, :workspace
35
+
36
+ def initialize(proj, ws)
37
+ @project = proj
38
+ @workspace = ws
39
+ end
40
+
41
+ def addListener(list)
42
+ end
43
+
44
+ def removeListener(list)
45
+ end
46
+
47
+ def value
48
+ self
49
+ end
50
+ end
51
+
52
+ class WorkspaceCellFactory < javafx.scene.control.TreeTableCell
53
+ include Antrapol::ToolRack::ExceptionUtils
54
+ def updateItem(itm,e)
55
+ super
56
+
57
+ cont = nil
58
+ if not itm.nil?
59
+ if itm.is_a?(TreeWorkspace)
60
+ if not_empty?(itm.workspace)
61
+ cont = itm.workspace.path
62
+ elsif not_empty?(itm.project)
63
+ cont = itm.project
64
+ else
65
+ cont = itm
66
+ end
67
+ else
68
+ cont = itm
69
+ end
70
+ end
71
+
72
+ setGraphic(Text.new(cont))
73
+
74
+ end
75
+ end
76
+
77
+
78
+ LEAF_PROJ_DESC = "Leaf Workspaces (Workspace without bind to a project)"
79
+ ALL_PROJ_FILTER = "All"
80
+ def init_tblWorkspace
81
+
82
+ @trtblWorkspace.columns.clear
83
+
84
+ @trtblWorkspace.placeholder = javafx.scene.control.Label.new("Add a workspace to begin")
85
+
86
+ @rootNode = TreeItem.new("Managed Workspaces")
87
+ @rootNode.expanded = true
88
+
89
+ # workspace that has not tie to any project
90
+ @leafProj = TreeItem.new(LEAF_PROJ_DESC)
91
+
92
+ @rootNode.children.add(@leafProj)
93
+
94
+ col = []
95
+ tcUrl = TreeTableColumn.new("Path")
96
+ tcUrl.cell_value_factory = Proc.new do |e|
97
+ #p e.value.value
98
+ if e.value.value.is_a?(TreeWorkspace)
99
+ e.value.value
100
+ else
101
+ SimpleStringProperty.new(e.value.value)
102
+ end
103
+ end
104
+ tcUrl.cell_factory = Proc.new do |tc|
105
+ WorkspaceCellFactory.new
106
+ end
107
+ col << tcUrl
108
+
109
+ tcLastAcc = TreeTableColumn.new("Last Access")
110
+
111
+ tcLastAcc.pref_width = 180.0
112
+ tcLastAcc.max_width = 180.0
113
+ tcLastAcc.min_width = 180.0
114
+
115
+ col << tcLastAcc
116
+
117
+
118
+ @trtblWorkspace.setRoot(@rootNode)
119
+ @trtblWorkspace.columns.add_all(col)
120
+ @trtblWorkspace.setShowRoot(true)
121
+
122
+
123
+ #@trtblWorkspace.columns.clear
124
+ @trtblWorkspace.column_resize_policy = javafx.scene.control.TreeTableView::CONSTRAINED_RESIZE_POLICY
125
+
126
+ #colUrl = TableColumn.new("Path")
127
+ #colUrl.cell_value_factory = Proc.new do |p|
128
+ # SimpleStringProperty.new(p.value.path)
129
+ #end
130
+
131
+ #colAccess = TableColumn.new("Last Access")
132
+ #colAccess.cell_value_factory = Proc.new do |p|
133
+ # SimpleStringProperty.new(p.value.last_access)
134
+ #end
135
+
136
+ #colAccess.pref_width = 180.0
137
+ #colAccess.max_width = colAccess.pref_width
138
+ #colAccess.min_width = colAccess.pref_width
139
+
140
+ #@trtblWorkspace.columns.add_all([colUrl, colAccess])
141
+
142
+ #@trtblWorkspace.selection_model.selection_mode = javafx.scene.control.SelectionMode::SINGLE
143
+
144
+ #@trtblWorkspace.selection_model.selected_items.add_listener do |evt|
145
+ @trtblWorkspace.selection_model.selected_item_property.add_listener do |obs, oldV, newV|
146
+ #puts "old value : #{oldV} / new value : #{newV}"
147
+ if not_empty?(newV)
148
+
149
+ if newV.value.is_a?(TreeWorkspace) and not_empty?(newV.value.workspace)
150
+
151
+ if File.exist?(newV.value.workspace.path)
152
+ # Here shall set a global reference to the selected workspace @selWs
153
+ @selWs = Gvcs::Workspace.new(Global.instance.vcs, newV.value.workspace.path)
154
+
155
+ refresh_details
156
+ show_details
157
+ else
158
+ show_landing
159
+ prompt_error("Workspace '#{newV.value.workspace.path}' does not exist anymore.\nPlease remove it from workspace.")
160
+ end
161
+
162
+ else
163
+ show_landing
164
+ end
165
+ else
166
+ show_landing
167
+ end
168
+ end
169
+
170
+ # project filter
171
+ @cmbWorkspaceProjectFilter.value_property.add_listener(Proc.new do |ov, oldV, newV|
172
+ # Javafx combobox not allow changing of internal value while it is updated
173
+ # if not enclosed in the Platform.run_later()
174
+ # java.lang.IndexOutOfBoundsException shall be thrown
175
+ Platform.run_later do
176
+
177
+ @projectFilter = newV
178
+
179
+ if not_empty?(newV)
180
+
181
+ # here shall change the listing of the project
182
+ refresh_workspace_list
183
+
184
+ end
185
+ end
186
+ end)
187
+
188
+ refresh_workspace_list
189
+
190
+ end
191
+
192
+ def trtblWorkspace_onMouseClicked(evt)
193
+ if evt.button == javafx.scene.input.MouseButton::SECONDARY
194
+ # right click on item
195
+ trtblWorkspace_ctxmnu.show(@trtblWorkspace, evt.screen_x, evt.screen_y)
196
+ #elsif evt.button == javafx.scene.input.MouseButton::PRIMARY and evt.click_count == 2
197
+ # # double click on item - diff file
198
+ # sel = @tblChanges.selection_model.selected_items
199
+ # if sel.length > 0
200
+ # sel.each do |s|
201
+ # st, res = @selWs.diff_file(s.path)
202
+ # if st
203
+
204
+ # show_content_win("Diff Output", "Diff Result - #{s.path}", res)
205
+
206
+ # else
207
+ # set_err_gmsg("Diff for '#{s.path}' failed. [#{res}]")
208
+ # end
209
+
210
+ # end
211
+ # end
212
+
213
+ end
214
+
215
+ end
216
+
217
+ # hooked to button Add
218
+ def workspace_add(evt)
219
+
220
+ path = @txtWorkspacePath.text
221
+ if not_empty?(path)
222
+
223
+ db = Global.instance.storage
224
+
225
+ if not File.exist?(path)
226
+ prompt_error("Given path '#{path}' does not exist. Please make sure it is a valid path.","Given Path Invalid",main_stage)
227
+ elsif db.is_workspace_registered?(path)
228
+ prompt_info("Given path '#{path}' already exist in the list.", "Path Already Exist", main_stage)
229
+ else
230
+
231
+ add_workspace(path)
232
+ set_success_gmsg("Workspace '#{path}' added to list")
233
+
234
+ end # if given path not exist
235
+
236
+ else
237
+ prompt_error "Please provide a folder path for Add operation", "Empty Path", main_stage
238
+ end
239
+
240
+ end
241
+
242
+ def trtbleWorkspace_keyreleased(evt)
243
+ if evt.code == javafx.scene.input.KeyCode::DELETE
244
+ sel = @trtblWorkspace.selection_model.selected_item
245
+ remove_workspace(sel)
246
+ end
247
+ end
248
+
249
+ def trtblWorkspace_dnd_dropped(evt)
250
+ dnd_dropped(evt)
251
+ evt.drop_completed = true
252
+ end
253
+
254
+ def trtblWorkspace_dnd_over(evt)
255
+ evt.acceptTransferModes(javafx.scene.input.TransferMode::LINK)
256
+ end
257
+
258
+ def landing_dnd_dropped(evt)
259
+ dnd_dropped(evt)
260
+ evt.drop_completed = true
261
+ end
262
+
263
+ def landing_dnd_over(evt)
264
+ evt.acceptTransferModes(javafx.scene.input.TransferMode::LINK)
265
+ end
266
+
267
+
268
+ def refresh_workspace_list
269
+ db = Global.instance.storage(true)
270
+
271
+ @rootNode.children.clear
272
+
273
+ log_debug "#{db.workspaces.length} project(s) found"
274
+
275
+ if db.workspaces.length > 0
276
+
277
+ db.workspaces.keys.sort.each do |k|
278
+
279
+ if not_empty?(@projectFilter) and @projectFilter != ALL_PROJ_FILTER
280
+ next if k != @projectFilter
281
+ end
282
+
283
+ tws = TreeWorkspace.new(k,nil)
284
+ pTi = TreeItem.new(tws)
285
+ db.workspaces[k].each do |ws|
286
+ ctws = TreeWorkspace.new(k,ws)
287
+ pTi.children.add(TreeItem.new(ctws))
288
+ end
289
+
290
+ @rootNode.children.add(pTi)
291
+ end
292
+
293
+ @cmbWorkspaceProjectFilter.items.clear
294
+ pf = [ALL_PROJ_FILTER]
295
+ pf.concat(db.parent.sort)
296
+ @cmbWorkspaceProjectFilter.items.add_all(pf)
297
+
298
+ # this is so far most acceptable version
299
+ # if set value will trigger the listener above that shall trigger this method again
300
+ # become vicious cycle
301
+ @cmbWorkspaceProjectFilter.prompt_text = @projectFilter if not_empty?(@projectFilter)
302
+
303
+ #show_details
304
+ else
305
+ show_landing
306
+ end
307
+
308
+ @selWs = nil
309
+
310
+ end
311
+
312
+ def show_details
313
+ @pnlLanding.visible = false
314
+ @tabPnlDetails.visible = true
315
+ end
316
+
317
+ def show_landing
318
+ @pnlLanding.visible = true
319
+ @tabPnlDetails.visible = false
320
+ end
321
+
322
+ #def workspace_key_released(evt)
323
+ # if evt.code == javafx.scene.input.KeyCode::DELETE
324
+ # sel = @trtblWorkspace.selection_model.selected_items.to_a
325
+ # if sel.length > 0
326
+ # s = sel.first.path
327
+ # res = fx_alert_confirmation("Delete workspace '#{s}' from system?\nThis won't affect physical file.", nil, "Remove Path from Management?", main_stage)
328
+ # if res == :ok
329
+ # Global.instance.storage.remove_workspace(s)
330
+ # Global.instance.storage.store
331
+ # refresh_workspace_list
332
+ # refresh_details
333
+ # log_debug "Workspace '#{s}' removed from management"
334
+ # set_info_gmsg("Workspace '#{s}' removed from management")
335
+ # else
336
+ # set_err_gmsg("Workspace delete operation aborted")
337
+ # end
338
+ # end
339
+
340
+ # end
341
+ #end
342
+
343
+ def open_workspace(evt)
344
+ dc = javafx.stage.DirectoryChooser.new
345
+ dc.title = "Select VCS Workspace"
346
+ wsDir = dc.showDialog(main_stage)
347
+
348
+ @txtWorkspacePath.text = wsDir.absolute_path
349
+ end
350
+
351
+ private
352
+ def dnd_dropped(evt)
353
+ f = evt.dragboard.files
354
+ vcs = Gvcs::Vcs.new
355
+ ws = []
356
+ nws = []
357
+ f.each do |ff|
358
+ log_debug "Checking drop in path '#{ff.absolute_path}'"
359
+ st, path = Gvcs::Workspace.new(vcs, ff.absolute_path).workspace_root
360
+ if st
361
+ # workspace!
362
+ ws << path.strip
363
+ else
364
+ # not a workspace
365
+ nws << ff.absolute_path
366
+ end
367
+ end
368
+
369
+ ws.each do |w|
370
+ log_debug "Adding workspace '#{w}'"
371
+ add_workspace(w)
372
+ set_success_gmsg("Workspace '#{w}' added to list")
373
+ end
374
+
375
+ failed = { }
376
+ nws.each do |w|
377
+ log_debug "Adding non workspace '#{w}'"
378
+ st, res = vcs.init(w)
379
+ if st
380
+ add_workspace(w)
381
+ set_success_gmsg("Non-workspace '#{w}' added to list")
382
+ else
383
+ failed[w] = res
384
+ end
385
+ end
386
+
387
+ raise_event(Listener::Event[:workspace_added])
388
+
389
+ end # dnd_dropped
390
+
391
+ def add_workspace(path)
392
+
393
+ raise_if_empty?(path, "Path cannot be empty in add workspace operation", GvcsFxException)
394
+
395
+ db = Global.instance.storage
396
+ awStage = javafx.stage.Stage.new
397
+ dlg = AddWorkspaceController.load_into(awStage)
398
+ # load existing projects into the combobox
399
+ if db.parent.length > 0
400
+ db.parent.each do |pa|
401
+ dlg.add_option(pa)
402
+ end
403
+ else
404
+ dlg.add_option(LEAF_PROJ_DESC)
405
+ end
406
+
407
+ # set the given path
408
+ dlg.path = path
409
+ awStage.title = "Add Workspace"
410
+ awStage.init_owner(main_stage)
411
+
412
+ awStage.showAndWait
413
+
414
+ res = dlg.result
415
+
416
+ if not_empty?(res)
417
+
418
+ projName = nil
419
+ if not is_empty?(res[0])
420
+ if res[0] == AddWorkspaceController::ADDPROJ_KEY
421
+ if is_empty?(res[1])
422
+ prompt_error("Project name is required. Please try again")
423
+ else
424
+ projName = res[1]
425
+ end
426
+ else
427
+ projName = res[0]
428
+ end
429
+
430
+ else
431
+ projName = LEAF_PROJ_DESC
432
+ end
433
+
434
+ if not_empty?(projName)
435
+
436
+ vcs = Gvcs::Vcs.new
437
+ ds = Global.instance.storage
438
+
439
+ tws = Gvcs::Workspace.new(vcs, path)
440
+ vcs.init(path) if not tws.is_workspace?
441
+ ds.add_workspace(projName,path)
442
+ ds.store
443
+ refresh_workspace_list
444
+ @txtWorkspacePath.clear
445
+
446
+ end
447
+
448
+ end
449
+
450
+ end # add_workspace
451
+
452
+ def remove_workspace(sel)
453
+
454
+ if not_empty?(sel)
455
+ txt = sel.value
456
+ db = Global.instance.storage
457
+
458
+ if txt.is_a?(TreeWorkspace)
459
+
460
+ if not_empty?(txt.workspace)
461
+
462
+ if db.is_workspace_registered?(txt.workspace.path)
463
+ # leaf
464
+ s = txt.workspace.path
465
+ res = fx_alert_confirmation("Delete workspace '#{s}' from system?\nThis won't affect physical file.", nil, "Remove Path from Management?", main_stage)
466
+ if res == :ok
467
+ db.remove_workspace(s)
468
+ db.store
469
+ set_success_gmsg("Workspace '#{s}' removed from management")
470
+ refresh_workspace_list
471
+ end
472
+ end
473
+
474
+ else
475
+ # project
476
+ if db.is_project_registered?(txt.project) and db.is_project_empty?(txt.project)
477
+ res = fx_alert_confirmation("Remove project '#{txt.project}' from the list?", nil, "Confirmation to Remove Project", main_stage)
478
+ if res == :ok
479
+ db.delete_project(txt.project)
480
+ db.store
481
+ set_success_gmsg("Project '#{txt.project}' removed from management")
482
+ refresh_workspace_list
483
+ end
484
+ end
485
+ end
486
+ end # txt.is_a?(TreeWorkspace)
487
+
488
+ end
489
+
490
+ end
491
+
492
+ def trtblWorkspace_ctxmnu
493
+
494
+ @ctxSel = @trtblWorkspace.selection_model.selected_item
495
+ trtblWsCtxMenu = javafx.scene.control.ContextMenu.new
496
+
497
+ if not_empty?(@ctxSel) and @ctxSel.value.is_a?(TreeWorkspace)
498
+
499
+ db = Global.instance.storage
500
+ tws = @ctxSel.value
501
+ if not_empty?(tws.workspace)
502
+ if db.is_workspace_registered?(tws.workspace.path)
503
+ #
504
+ # leaf
505
+ #
506
+ # delete menu item
507
+ #
508
+ delMnuItm = javafx.scene.control.MenuItem.new("Remove from management")
509
+ delMnuItm.on_action do |evt|
510
+
511
+ remove_workspace(@ctxSel)
512
+
513
+ end
514
+ trtblWsCtxMenu.items.add(delMnuItm)
515
+ #
516
+ # end diff menu item
517
+ #
518
+ end
519
+ else
520
+ # project
521
+ if db.is_project_empty?(tws.project)
522
+ #
523
+ # delete menu item
524
+ #
525
+ delMnuItm = javafx.scene.control.MenuItem.new("Remove from management")
526
+ delMnuItm.on_action do |evt|
527
+
528
+ remove_workspace(@ctxSel)
529
+
530
+ end
531
+ trtblWsCtxMenu.items.add(delMnuItm)
532
+ #
533
+ # end diff menu item
534
+ #
535
+
536
+ end
537
+
538
+ end
539
+
540
+ end
541
+
542
+
543
+ trtblWsCtxMenu
544
+ end
545
+
546
+ end
547
+ end