gvcsfx 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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