1 namespace gui::controls;
5 default extern int __ecereVMethodID_class_OnGetDataFromString;
6 default static void _workAround()
9 a.OnGetDataFromString(0);
13 /* We need a dynamic cast :) Easy eC compiler introduction contribution! :)
14 static define pathBoxDataBox = dynamic_cast(pathBox.master);
15 static define pathBoxListBox = pathBoxEditorDataBox ? dynamic_cast((pathBoxDataBox).parent) : null;
16 static define pathBoxDirsBox = pathBoxEditorListBox ? dynamic_cast((pathBoxListBox).parent) : null;
18 static Class _classDataBox() { return class(DataBox); }
19 static Class _classListBox() { return class(ListBox); } // Fix #908
20 static Class _classDirectoriesBox() { return class(DirectoriesBox); }
21 static define pathBoxDataBox = eClass_IsDerived( pathBox.master._class, _classDataBox() ) ? (DataBox)pathBox.master : null;
22 static define pathBoxListBox = (pathBoxDataBox && eClass_IsDerived((pathBoxDataBox).parent._class, _classListBox() )) ? (ListBox)(pathBoxDataBox).parent : null;
23 static define pathBoxDirsBox = (pathBoxListBox && eClass_IsDerived((pathBoxListBox).parent._class, _classDirectoriesBox())) ? (DirectoriesBox)(pathBoxListBox).parent : null;
25 public class FilePath : String
27 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
31 dataBox, borderStyle = 0, anchor = { 0, 0, 0, 0 },
35 DirectoriesBox dirsBox = pathBoxDirsBox;
37 pathBox.browseDialog = dirsBox.browseDialog;
38 // TOCHECK: compiler issues?
39 /*else if(userData && eClass_IsDerived(userData._class, class(FileDialog)))
40 pathBox.browseDialog = (FileDialog)userData;*/
42 pathBox.browseDialog = { type = open, text = $"Select a file..." };
47 bool OnSaveEdit(PathBox pathBox, void * object)
50 if(pathBox.modifiedDocument)
52 DirectoriesBox dirsBox = pathBoxDirsBox;
54 dirsBox.NotifyPathBoxModified(dirsBox.master, dirsBox, pathBox);
56 changed = ((bool (*)(void *, void *, const char *))(void *)_class._vTbl[__ecereVMethodID_class_OnGetDataFromString])(_class, &this, pathBox.systemPath);
61 int OnCompare(DirPath b)
63 return fstrcmp(this, b);
67 public class DirPath : FilePath
69 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
73 dataBox, borderStyle = 0, anchor = { 0, 0, 0, 0 },
74 typeExpected = directory;
77 DirectoriesBox dirsBox = pathBoxDirsBox;
79 pathBox.browseDialog = dirsBox.browseDialog;
80 // TOCHECK: compiler issues? (same)
81 /*else if(userData && eClass_IsDerived(userData._class, class(FileDialog)))
82 pathBox.browseDialog = (FileDialog)userData;*/
84 pathBox.browseDialog = { type = selectDir, text = $"Select a folder..." };
89 bool OnSaveEdit(PathBox pathBox, void * object)
92 if(pathBox.modifiedDocument)
94 DirectoriesBox dirsBox = pathBoxDirsBox;
96 dirsBox.NotifyPathBoxModified(dirsBox.master, dirsBox, pathBox);
98 changed = ((bool (*)(void *, void *, const char *))(void *)_class._vTbl[__ecereVMethodID_class_OnGetDataFromString])(_class, &this, pathBox.systemPath);
105 public enum PathTypeExpected { none, any, directory, file };
107 public class PathBox : CommonControl
110 clientSize = { 64, 18 };
112 watch(background) { editBox.background = background; };
113 watch(foreground) { editBox.foreground = foreground; };
114 watch(selectionColor) { editBox.selectionColor = selectionColor; };
115 watch(selectionText) { editBox.selectionText = selectionText; };
116 watch(opacity) { editBox.opacity = opacity; };
118 #if defined(__WIN32__)
125 PathTypeExpected typeExpected;
126 FileDialog browseDialog;
127 #if defined(__WIN32__)
128 char path[MAX_LOCATION];
131 BitmapResource file { "<:ecere>mimeTypes/file.png", transparent = true, alphaBlend = true };
132 BitmapResource brokenFile { "<:ecere>mimeTypes/brokenFile.png", transparent = true, alphaBlend = true };
133 BitmapResource folder { "<:ecere>places/folder.png", transparent = true, alphaBlend = true };
134 BitmapResource brokenFolder { "<:ecere>places/brokenFolder.png", transparent = true, alphaBlend = true };
138 this/*, size = { 318, 94 }*/, anchor = { left = 1, vert = 0 };
139 image = brokenFolder;
145 public property EditBox editBox { get { return editBox; } }
148 this/*, size = { 290, 22 }*/, position = { 1, 1 }, anchor = { left = 1, top = 1, right = 1 };
151 void NotifyUpdate(EditBox editBox)
154 modifiedDocument = true;
156 bool NotifyModified(EditBox editBox)
158 PathBox pathBox = this;
159 DirectoriesBox dirsBox = pathBoxDirsBox;
161 dirsBox.NotifyPathBoxModified(dirsBox.master, dirsBox, this);
162 return NotifyModified(master, this);
165 /* F4? F4 is properties, f2 works already for this
166 bool OnKeyDown(Key key, unichar ch)
169 ((PathBox)parent).browse.NotifyClicked(parent, ((PathBox)parent).browse, 0, 0, (Modifiers)null);
170 return EditBox::OnKeyDown(key, ch);
175 // For chaining popup-key event
176 bool OnKeyHit(Key key, unichar ch)
178 return editBox.OnKeyHit(key, ch);
183 this, size = { w = 26 }, anchor = { top = 0, right = 0, bottom = 0 };
189 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
193 char browsePath[MAX_LOCATION];
194 char * baseBrowsePath = null;
195 PathBox pathBox = this;
196 DataBox dataBox = pathBoxDataBox;
198 DirectoriesBox dirsBox = pathBoxDirsBox;
199 char * ebContents = editBox.contents;
200 String backFilePath = CopyString(browseDialog.filePath);
202 browsePath[0] = '\0';
203 strncpy(browsePath, browseDialog.filePath, MAX_LOCATION); browsePath[MAX_LOCATION-1] = '\0';
204 if(dirsBox && dirsBox.baseBrowsePath && dirsBox.baseBrowsePath[0] && ((ebContents && ebContents[0]) || !backFilePath || !backFilePath[0]))
205 PathCat(browsePath, dirsBox.baseBrowsePath);
206 PathCat(browsePath, ebContents);
207 browseDialog.filePath = (ebContents && ebContents[0]) ? browsePath : "";
208 if(pathBox.typeExpected == directory && browsePath[0] && FileExists(browsePath).isDirectory && backFilePath && backFilePath[0])
209 StripLastDirectory(browsePath, browsePath);
210 while(browsePath[0] && !FileExists(browsePath).isDirectory)
211 StripLastDirectory(browsePath, browsePath);
214 char path[MAX_LOCATION];
215 LocateModule(null, path);
216 StripLastDirectory(path, path);
217 strncpy(browsePath, path, MAX_LOCATION); browsePath[MAX_LOCATION-1] = '\0';
219 browseDialog.currentDirectory = browsePath;
220 browseDialog.master = rootWindow;
223 if(dirsBox) dirsBox.browsing = true;
224 if(browseDialog.Modal())
226 PathBox pathBox = dataBox ? (PathBox)dataBox.editor : this;
227 pathBox.modifiedDocument = true;
228 pathBox.property::path = browseDialog.filePath;
229 pathBox.NotifyModified(pathBox.master, this);
233 pathBox.editBox.SelectAll();
234 if((listBox = pathBoxListBox))
235 listBox.StopEditing(true);
238 browseDialog.filePath = backFilePath;
240 if(dirsBox) dirsBox.browsing = false;
247 void CheckFileExists()
249 if(typeExpected != none)
251 BitmapResource icon = null;
252 char path[MAX_LOCATION];
253 FileAttribs exists { };
254 GetSystemPathBuffer(path, editBox.contents);
255 if(!(path[0] == DIR_SEP && path[1] == DIR_SEP && (!path[2] || !strchr(&path[2], DIR_SEP))))
256 exists = FileExists(path);
261 // TODO: improvements, add drive, etc, also find a better solution/icon for expect any and file doesn't exist
262 icon = exists ? exists.isFile ? file : exists.isDirectory ? folder : null : null;
265 icon = exists && exists.isDirectory ? folder : brokenFolder;
268 icon = exists && exists.isFile ? file : brokenFile;
272 picture.image = icon;
276 void OnRedraw(Surface surface)
280 surface.SetBackground(formColor);
281 surface.Area(0, 0, clientSize.w, clientSize.h);
284 Window::OnRedraw(surface);
293 virtual bool Window::NotifyModified(PathBox pathBox);
295 property PathTypeExpected typeExpected
299 if(value != typeExpected)
301 if(value == none || typeExpected == none)
303 bool withIcon = value != none;
304 picture.visible = withIcon;
305 editBox.anchor.left = withIcon ? 18 : 1;
308 typeExpected = value;
309 if(browseDialog && browseDialog.type == open && typeExpected == directory)
310 browseDialog.type = selectDir;
315 property FileDialog browseDialog
320 browseDialog = value;
324 if(browseDialog.type == open && typeExpected == directory)
325 browseDialog.type = selectDir;
326 if(!strcmp(browseDialog.text, "Select a file...") && text)
328 char temp[1024] = "Select ";
331 browseDialog.text = temp;
334 browse.visible = browseDialog ? true : false;
335 editBox.anchor.right = browseDialog ? 26 : 1;
337 get { return browseDialog; }
340 void Home() { editBox.Home(); }
341 void End() { editBox.End(); }
343 void SelectAll() { editBox.SelectAll(); }
344 void Deselect() { editBox.Deselect(); }
350 char path[MAX_LOCATION];
351 GetSystemPathBuffer(path, value);
352 editBox.contents = path;
357 get { return editBox.contents; }
359 property String slashPath { get { return GetSlashPathBuffer (path, editBox.contents); } };
360 property String systemPath { get { return GetSystemPathBuffer(path, editBox.contents); } };
362 property Color selectionColor { set { editBox.selectionColor = value; } get { return editBox.selectionColor; }/* isset { return selectionColor ? true : false; }*/ };
363 property Color selectionText { set { editBox.selectionText = value; } get { return editBox.selectionText; }/* isset { return selectionText ? true : false; }*/ };
367 FileDialog browseFileDialog { type = selectDir, text = $"Select directory" };
369 public class DirectoriesBox : CommonControl
371 FileDialog browseDialog;
372 char * baseBrowsePath;
380 virtual bool Window::NotifyModified(DirectoriesBox dirsBox);
381 virtual bool Window::NotifyPathBoxModified(DirectoriesBox dirsBox, PathBox pathBox);
383 virtual bool OnChangedDir(char ** directory);
384 virtual bool OnPrepareBrowseDir(char ** directory);
385 virtual bool OnBrowsedDir(char ** directory);
387 watch(foreground) { list.foreground = foreground; };
388 watch(background) { list.background = background; };
389 //watch(selectionColor) { list.selectionColor = selectionColor; };
390 //watch(selectionText) { list.selectionText = selectionText; };
391 watch(opacity) { list.opacity = opacity; };
393 property Array<String> strings
402 char temp[MAX_LOCATION];
403 list.AddString(GetSystemPathBuffer(temp, s));
407 list.currentRow = list.firstRow;
408 list.modifiedDocument = false;
412 Array<String> array { };
414 for(row = list.firstRow; row; row = row.next)
416 String string = row.string;
417 if(string && string[0])
418 array.Add(CopyUnixPath(string));
424 property FileDialog browseDialog
429 browseDialog = value;
433 if(browseDialog.type == open)
434 browseDialog.type = selectDir;
435 if(!strcmp(browseDialog.text, "Select a file...") && text)
437 char temp[1024] = "Select ";
440 browseDialog.text = temp;
444 get { return browseDialog; }
447 property String baseBrowsePath
451 delete baseBrowsePath;
453 baseBrowsePath = CopyString(value);
455 get { return baseBrowsePath; }
458 bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
460 // Browsing was not being set, fixed by introducing dependency to this class to PathBox
461 if(!active && !browsing)
463 list.StopEditing(true);
464 if(list.modifiedDocument)
466 NotifyModified(master, this);
467 list.modifiedDocument = false;
468 modifiedDocument = true;
476 parent = this, bevelOver = true, inactive = true;
477 position = { 265, 0 }, size = { 22, 22 };
478 anchor = { top = 0, right = 77 };
479 hotKey = plus, bitmap = BitmapResource { fileName = "<:ecere>actions/listAdd.png", alphaBlend = true };
480 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
482 list.StopEditing(true);
483 list.lastRow.Edit(null);
484 list.modifiedDocument = true;
490 parent = this, bevelOver = true, inactive = true;
491 position = { 290, 0 }, size = { 22, 22 };
492 anchor = { top = 0, right = 54 };
493 hotKey = del, bitmap = BitmapResource { fileName = "<:ecere>actions/listRemove.png", alphaBlend = true };
494 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
496 list.StopEditing(true);
497 if(list.currentRow != list.lastRow)
499 list.DeleteRow(null);
500 list.modifiedDocument = true;
507 parent = this, bevelOver = true, inactive = true;
508 position = { 315, 0 }, size = { 22, 22 };
509 anchor = { top = 0, right = 31 };
510 hotKey = ctrlUp, bitmap = BitmapResource { fileName = "<:ecere>actions/goUp.png", alphaBlend = true };
511 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
513 if(list.currentRow != list.lastRow)
515 DataRow current = list.currentRow, row;
518 row = current.previous;
523 list.modifiedDocument = true;
532 parent = this, bevelOver = true, inactive = true;
533 position = { 340, 0 }, size = { 22, 22 };
534 anchor = { top = 0, right = 8 };
535 hotKey = ctrlDown, bitmap = BitmapResource { fileName = "<:ecere>actions/goDown.png", alphaBlend = true };
536 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
538 DataRow current = list.currentRow, row;
542 if(row && row != list.lastRow)
545 list.modifiedDocument = true;
553 this, moveRows = true, hasVertScroll = true, dontHideScroll = true;
554 borderStyle = deep, position = { 0, 22 }, size = { 300, 60 };
555 anchor = { left = 0, top = 22, right = 0, bottom = 0 };
557 bool OnRightButtonDown(int x, int y, Modifiers mods)
559 return parent.OnRightButtonDown(x + position.x + parent.clientStart.x, y + position.y + parent.clientStart.y, mods);
562 bool NotifyChanged(ListBox listBox, DataRow row)
564 char * directory = listBox.GetData(null);
565 if(directory && directory[0])
567 char * dir = CopyString(directory);
568 if(OnChangedDir(&dir))
570 // Put this back to enable making Paths relative by overriding
571 // these DirectoriesBox virtual methods (from FileDialog only)
574 OnPrepareBrowseDir(&dir);
577 listBox.SetData(null, dir);
578 listBox.modifiedDocument = true;
579 if(listBox.currentRow == listBox.lastRow && listBox.lastRow.string)
581 DataRow r = listBox.lastRow;
583 listBox.currentRow = listBox.AddString("");
588 else if(listBox.currentRow != listBox.lastRow)
590 listBox.DeleteRow(null);
591 listBox.modifiedDocument = true;
596 bool NotifyEditDone(ListBox listBox, DataRow row)
601 bool NotifyKeyHit(ListBox listBox, DataRow row, Key key, unichar ch)
603 // Prioritize row moving Ctrl-Up/Down over scrollbar scrolling
604 if(key == ctrlUp || key == ctrlDown)
606 Button btn = (key == ctrlUp) ? up : down;
607 btn.OnKeyHit(hotKey, 0);
613 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
615 // Prioritize row moving Ctrl-Up/Down over scrollbar scrolling
616 if(key == ctrlUp || key == ctrlDown)
618 Button btn = (key == ctrlUp) ? up : down;
619 btn.OnKeyDown(hotKey, 0);
624 listBox.StopEditing(true);
625 if(listBox.currentRow != listBox.lastRow)
626 listBox.DeleteRow(null);
632 bool NotifyMove(ListBox listBox, DataRow row, Modifiers mods)
634 if(listBox.currentRow == listBox.lastRow)
636 else if(row == listBox.lastRow)
638 if(listBox.currentRow == row.previous)
640 listBox.currentRow.Move(row.previous);
646 bool NotifyReclick(ListBox listBox, DataRow row, Modifiers mods)
652 DataField dirField { dataType = class(DirPath), editable = true };
656 incref browseFileDialog;
657 browseDialog = browseFileDialog;
658 list.AddField(dirField);
660 list.modifiedDocument = false;
665 delete baseBrowsePath;