1 | srecord noeq G22DatabasesPanel(G22Utils g22utils) { |
2 | delegate GazelleDB to G22Utils. |
3 | delegate masterStuff to g22utils. |
4 | |
5 | JObjectTable<GazelleDB> table; |
6 | FileWatchService dirWatcher; |
7 | ReliableSingleThread rstUpdate = new(r _updateTable); |
8 | |
9 | cachedVisualize { |
10 | table = swing(-> new JObjectTable); |
11 | table.defaultAction(runnableToIVF1(rThread openDB)); |
12 | table.itemToMap = db -> { |
13 | IG22LoadedDB loaded = db.loadedDB(); |
14 | ret litorderedmap( |
15 | "Name" := db.name, |
16 | "Directory" := f2s(db.dir), |
17 | "Loaded" := loaded == null ? "No" |
18 | : (loaded.hidden() ? "Yes (hidden)" : "Yes"); }; |
19 | |
20 | var tbl = table.visualize(); |
21 | bindToComponent(tbl, -> { |
22 | dirWatcher = new FileWatchService; |
23 | dirWatcher.addNonRecursiveListener(g22utils.databasesMotherDir(), file -> { |
24 | //print("G22DatabasesPanel File change: " + file); |
25 | rstUpdate!; |
26 | }); |
27 | masterStuff().onLoadedDBsChange(rstUpdate); |
28 | rstUpdate!; |
29 | }, -> { |
30 | masterStuff().removeLoadedDBsChangeListener(rstUpdate); |
31 | dispose dirWatcher; |
32 | }); |
33 | |
34 | ret withTopAndBottomMargin(jCenteredRaisedSection("Gazelle projects on this computer", |
35 | northAndCenterWithMargins( |
36 | jline( |
37 | toolTip("Create a new Gazelle project", jbutton("New project...", rThread newDatabase)) |
38 | ), |
39 | centerAndEastWithMargin( |
40 | tbl, |
41 | jscroll_vertical_borderless(vstackWithSpacing_fixed( |
42 | // BUTTONS defined here |
43 | |
44 | DefaultButtonBorder(toolTip("Open selected project, keep other projects open too", |
45 | tableDependentButton(table.table, "Open project", rThread openDB))), |
46 | toolTip("Open selected project in hidden mode [without a window]", |
47 | tableDependentButton(table.table, "Open hidden", rThread openDBHidden)), |
48 | toolTip("Open selected project, close all other projects", |
49 | tableDependentButton(table.table, "Switch to project", rThread switchToDB)), |
50 | tableDependentButton(table.table, "Close project", rThread closeDB), |
51 | tableDependentButton(table.table, "Rename project", rThread renameDB), |
52 | tableDependentButton(table.table, "Delete project...", rThread deleteDB), |
53 | tableDependentButton(table.table, "Browse files", rThread browse), |
54 | tableDependentButton(table.table, "Export project as zip...", rThread exportAsZip), |
55 | jThreadedButton("Import project from zip...", rThread importZip), |
56 | jThreadedButton("Download project from Gaz.AI...", rThread downloadProject), |
57 | ))))); |
58 | } |
59 | |
60 | void newDatabase { |
61 | temp g22utils.enter(); |
62 | |
63 | var tf = jtextfield(); |
64 | var lblDir = jlabel(" "); |
65 | var lblStatus = jlabel(" "); |
66 | var button = jThreadedButton("Create project", -> { |
67 | temp g22utils.enter(); |
68 | |
69 | S name = trim(tf.getText()); |
70 | File dir = newFile(g22utils.databasesMotherDir(), name); |
71 | createEmptyConceptsFileInDir(dir); |
72 | disposeFrame(tf); |
73 | |
74 | masterStuff().openDatabase(dir); |
75 | }); |
76 | disableButton(button); |
77 | onEnter(tf, button); |
78 | |
79 | onChange(tf, r { |
80 | S name = trim(tf.getText()); |
81 | bool ok; |
82 | S status = " ", path = " "; |
83 | if (isValidFileName(name)) { |
84 | File dir = newFile(g22utils.databasesMotherDir(), name); |
85 | path = f2s(dir); |
86 | if (dirExists(dir)) |
87 | status = "A project with that name exists"; |
88 | else |
89 | ok = true; |
90 | } else if (!empty(name)) |
91 | status = "Project name must be a valid file name"; |
92 | setEnabled(button, ok); |
93 | setText(lblStatus, status); |
94 | setText(lblDir, path); |
95 | }); |
96 | |
97 | showForm_makeFrame("New Gazelle Project", |
98 | vstackWithSpacing( |
99 | withLabel("Name for new project", tf), |
100 | lblDir, |
101 | lblStatus, |
102 | button); |
103 | } |
104 | |
105 | void _updateTable { table.setData_force(g22utils.gazelleDBs()); } |
106 | |
107 | void browse { desktopOpen(table.selected().dir); } |
108 | void openDB { masterStuff().openDatabase(table.selected().dir); } |
109 | void openDBHidden { masterStuff().openDatabase(table.selected().dir, true); } |
110 | void switchToDB { masterStuff().switchToDatabase(table.selected().dir); } |
111 | void closeDB { masterStuff().closeDatabase(table.selected().dir); } |
112 | |
113 | void deleteDB { |
114 | var db = table.selected(); |
115 | if (db == null) ret; |
116 | |
117 | var dir = db.dir(); |
118 | if (g22utils.isConceptsDir(dir)) |
119 | ret with messageBox("Can't delete current project"); |
120 | |
121 | // First, close the databse |
122 | masterStuff().closeDatabase(dir); |
123 | new DeleteFilesDialog("Delete Gazelle project " + db.name()) |
124 | .wholeDirectory(dir).show(); |
125 | } |
126 | |
127 | void exportAsZip { |
128 | // Get project directory to export |
129 | File projectDir = table.selected().dir; |
130 | |
131 | // Make up a zip name + place and let user decide where to actually put it |
132 | |
133 | new JFileChooser fileChooser; |
134 | fileChooser.setDialogTitle("Export project as zip"); |
135 | fileChooser.setSelectedFile(javaxBackupDir(projectDir.getName() + "-" + ymdMinusHMS() + ".zip")); |
136 | var cbSubdirs = jcheckbox("Include subdirectories", true); |
137 | fileChooser.setAccessory(withLeftMargin(cbSubdirs)); |
138 | |
139 | // Show dialog |
140 | if (fileChooser.showSaveDialog(visualize()) != JFileChooser.APPROVE_OPTION) ret; |
141 | |
142 | // User has confirmed, proceed with export |
143 | File zip = fileChooser.getSelectedFile(); |
144 | S prefix = projectDir.getName() + "/"; |
145 | if (isChecked(cbSubdirs)) |
146 | dir2zip_recurse(projectDir, zip, prefix); |
147 | else |
148 | dir2zip(projectDir, zip, prefix); |
149 | |
150 | // Show note |
151 | fileSavedInfoBox(zip); |
152 | |
153 | // Try to open in file manager |
154 | desktopOpen(dirOfFile(zip)); |
155 | } |
156 | |
157 | void importZip { pcall-messagebox { |
158 | new JFileChooser fc; |
159 | fc.setDialogTitle("Import project from zip"); |
160 | fc.setCurrentDirectory(javaxBackupDir()); |
161 | if (fc.showOpenDialog(visualize()) == JFileChooser.APPROVE_OPTION) { |
162 | File zip = fc.getSelectedFile(); |
163 | g22utils.importProjectFromZip(zip); |
164 | } |
165 | }} |
166 | |
167 | void downloadProject { |
168 | if (gazAICredentialsFromJavaXSecret() == null) |
169 | ret with messageBox("Please enter Gaz.AI credentials first"); |
170 | |
171 | inputText("Project to download", projectName -> { pcall-messagebox { |
172 | var zip = g22utils.downloadProjectFromGazAI(gazAICredentialsFromJavaXSecret(), projectName); |
173 | if (swingConfirm("Install downloaded project?")) |
174 | g22utils.importProjectFromZip(zip); |
175 | }}); |
176 | } |
177 | |
178 | void renameDB { |
179 | File dir = table.selected().dir; |
180 | |
181 | inputText("New name", fileName(dir), newName -> { |
182 | assertValidFileName(newName); |
183 | if (!eq(newName, fileName(dir))) { |
184 | bool open = masterStuff().isConceptDirLoaded(dir); |
185 | if (open) |
186 | masterStuff().closeDatabase(dir); |
187 | renameFileVerbose(dir, newName); |
188 | if (open) |
189 | masterStuff().openDatabase(dir); |
190 | } |
191 | }); |
192 | } |
193 | } |
1
Travelled to 1 computer(s): mqqgnosmbjvj
No comments. add comment
Snippet ID: | #4000003 |
Snippet name: | ubaTaeCJ |
Eternal ID of this version: | #4000003/1 |
Text MD5: | 0401533e34f18c86f38648b737aaba11 |
Author: | ubataecj |
Category: | 1 |
Type: | User-supplied dialog |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2024-04-06 17:29:21 |
Source code size: | 7049 bytes / 193 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 55 / 24 |
Referenced in: | [show references] |