1 #ifdef BUILDING_ECERE_COM
2 namespace gui::controls;
6 public import static "ecere"
12 // We have this dependency because of important 'browsing' to keep track
13 import "DirectoriesBox"
15 void MakeSlashPath(char * p)
19 ChangeCh(p, '\\', '/');
23 void MakeSystemPath(char * p)
26 #if defined(__WIN32__)
27 ChangeCh(p, '/', '\\');
29 ChangeCh(p, '\\', '/');
34 public char * CopySystemPath(char * p)
36 char * d = CopyString(p);
42 public char * CopyUnixPath(char * p)
44 char * d = CopyString(p);
50 public char * GetSystemPathBuffer(char * d, char * p)
53 strcpy(d, p ? p : "");
58 public char * GetSlashPathBuffer(char * d, char * p)
61 strcpy(d, p ? p : "");
66 public char * PathCatSlash(char * string, char * addedPath)
68 bool modified = false;
71 char fileName[MAX_LOCATION] = "", archiveName[MAX_LOCATION] = "", * file;
76 if(SplitArchivePath(string, archiveName, &file))
77 strcpy(fileName, file);
80 strcpy(fileName, string);
83 if(strstr(string, "http://") == string)
85 char * slash = strstr(fileName + 7, "/");
90 urlFileName = fileName + strlen(fileName);
92 if(strstr(addedPath, "http://") == addedPath)
94 strcpy(fileName, "http://");
98 else if(GetRuntimePlatform() == win32)
100 if(addedPath[0] && addedPath[1] == ':' && addedPath[0] != '<')
102 fileName[0] = (char)toupper(addedPath[0]);
108 else if(addedPath[0] == '\\' && addedPath[1] == '\\')
110 fileName[0] = fileName[1] = '\\';
115 // A drive needs to be selected
116 /* TOCHECK: Cutting this out, can't handle relative path
117 else if(fileName[0] == '/' && !archiveName[0] && strcmp(addedPath, "/"))
122 if(!modified && isURL && (addedPath[0] == '\\' || addedPath[0] == '/'))
124 urlFileName[0] = '/';
125 urlFileName[1] = '\0';
127 else if(!modified && (addedPath[0] == '\\' || addedPath[0] == '/'))
129 if(GetRuntimePlatform() == win32)
132 if(addedPath[0] == '/' && !addedPath[1])
134 fileName[0] = addedPath[0];
139 else if(fileName[0] && fileName[1] == ':')
144 // Relative path root of drive
161 for(; addedPath[c]; )
163 // DANGER OF OVERFLOW HERE
164 // char directory[MAX_FILENAME];
165 char directory[MAX_FILENAME * 16];
170 for(;(ch = addedPath[c]) && (ch == '/' || ch == '\\'); c++);
171 for(;(ch = addedPath[c]) && (ch != '/' && ch != '\\'); c++)
173 if(isURL && ch == '?')
177 if(len < MAX_FILENAME)
178 directory[len++] = ch;
180 directory[len] = '\0';
182 // Trim rightmost spaces
183 for(count = len-1; count >= 0 && (directory[count] == ' ' || directory[count] == '\t'); count--)
185 directory[count] = '\0';
192 if(strstr(directory, "..") == directory && (!directory[2] || directory[2] == DIR_SEP || directory[2] == '/'))
194 int strLen = strlen(fileName) - 1;
197 // Go back one directory
198 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--);
199 for(;(ch = fileName[strLen]) && strLen > -1 && (ch != '/' && ch != '\\' && ch != ':'); strLen--);
200 for(;(ch = fileName[strLen]) && strLen > -1 && (ch == '/' || ch == '\\'); strLen--);
204 strLen = Max(strLen, urlFileName - fileName);
206 if(!strcmp(fileName + strLen + 1, ".."))
208 strcat(fileName, "/" /*DIR_SEPS*/);
209 strcat(fileName, "..");
213 if(GetRuntimePlatform() == win32)
215 if(!strLen && fileName[0] == '\\' && fileName[1] == '\\')
227 fileName[strLen+1] = '\0';
231 fileName[strLen+1] = '\0';
243 strcpy(fileName, "..");
246 else if(strcmp(directory, "."))
248 int strLen = strlen(fileName);
249 bool notZeroLen = strLen > 0;
250 // if(strLen > 1 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
251 if(strLen > 0 && (fileName[strLen-1] == '/' || fileName[strLen-1] == '\\'))
253 if(notZeroLen /*&& fileName[strLen-1] != ':' && fileName[strLen-1] != '>'*/)
254 fileName[strLen++] = '/';
256 fileName[strLen] = '\0';
258 if(strLen + strlen(directory) > MAX_LOCATION - 3)
259 return null; // AN ERROR OCCURED!
261 strcat(fileName, directory);
264 if(isURL && ch == '/')
265 strcat(fileName, "/");
266 if(isURL && ch == '?')
268 strcat(fileName, addedPath+c);
273 sprintf(string, "<%s>%s", archiveName, fileName);
275 strcpy(string, fileName);
277 return modified ? string : null;
280 default extern int __ecereVMethodID_class_OnGetDataFromString;
281 default static void _workAround()
284 a.OnGetDataFromString(0);
287 public class DirPath : String
289 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
293 dataBox, borderStyle = 0, anchor = { 0, 0, 0, 0 },
294 browseDialog = (FileDialog)userData;
297 void OnPathBrowsed(char * browsedPath)
299 DataBox dataBox = (DataBox)parent;
300 ListBox lb = eClass_IsDerived(dataBox.parent._class, class(ListBox)) ? (ListBox)dataBox.parent : null;
301 property::path = browsedPath;
302 if(lb) lb.StopEditing(true);
306 pathBox.visible = true;
310 pathBox.editBox.Deselect();
311 pathBox.editBox.Home();
316 bool OnSaveEdit(PathBox pathBox, void * object)
318 bool changed = false;
319 if(pathBox.modifiedDocument)
322 char path[MAX_LOCATION];
323 char * c = pathBox.path;
324 GetSystemPathBuffer(path, c);
326 pathBox.editBox.contents = path;
330 // changed = String::OnGetDataFromString(path); // TODO: Fix Me
331 changed = _class._vTbl[__ecereVMethodID_class_OnGetDataFromString](_class, &this, pathBox.systemPath);
336 int OnCompare(DirPath b)
338 return fstrcmp(this, b);
343 public enum PathTypeExpected { none, any, directory, file };
345 public class PathBox : CommonControl
348 clientSize = { 64, 18 };
350 #if defined(__WIN32__)
357 PathTypeExpected typeExpected;
358 FileDialog browseDialog;
359 #if defined(__WIN32__)
360 char path[MAX_LOCATION];
363 BitmapResource file { "<:ecere>mimeTypes/file.png", transparent = true, alphaBlend = true };
364 BitmapResource brokenFile { "<:ecere>mimeTypes/brokenFile.png", transparent = true, alphaBlend = true };
365 BitmapResource folder { "<:ecere>places/folder.png", transparent = true, alphaBlend = true };
366 BitmapResource brokenFolder { "<:ecere>places/brokenFolder.png", transparent = true, alphaBlend = true };
370 this/*, size = { 318, 94 }*/, anchor = { left = 1, vert = 0 };
371 image = brokenFolder;
379 this/*, size = { 290, 22 }*/, position = { 1, 1 }, anchor = { left = 1, top = 1, right = 1 };
382 void NotifyUpdate(EditBox editBox)
385 modifiedDocument = true;
387 bool NotifyModified(EditBox editBox)
389 return NotifyModified(master, this);
392 bool OnKeyDown(Key key, unichar ch)
395 ((PathBox)parent).browse.NotifyClicked(parent, ((PathBox)parent).browse, 0, 0, (Modifiers)null);
396 return EditBox::OnKeyDown(key, ch);
400 // For chaining popup-key event
401 bool OnKeyHit(Key key, unichar ch)
403 return editBox.OnKeyHit(key, ch);
408 this, size = { w = 26 }, anchor = { top = 0, right = 0, bottom = 0 };
414 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
418 char * browsePath = CopyString(OnBrowse());
419 char fileName[MAX_LOCATION];//, filePath[MAX_LOCATION];
420 DirectoriesBox dirBox = (DirectoriesBox)parent.parent;
421 if(dirBox) { dirBox = (DirectoriesBox)dirBox.parent; } // TOFIX: Precomp needs { }
422 if(dirBox && !eClass_IsDerived(dirBox._class, class(DirectoriesBox))) dirBox = null;
426 GetLastDirectory(browsePath, fileName);
427 StripLastDirectory(browsePath, browsePath);
431 char filePath[MAX_LOCATION];
433 LocateModule(null, filePath);
434 StripLastDirectory(filePath, filePath);
435 browsePath = CopyString(filePath);
438 while(browsePath[0] && !FileExists(browsePath).isDirectory)
440 char temp[MAX_LOCATION];
441 GetLastDirectory(browsePath, temp);
442 PathCat(temp, fileName);
443 strcpy(fileName, temp);
444 StripLastDirectory(browsePath, browsePath);
446 browseDialog.filePath = fileName;
447 browseDialog.currentDirectory = browsePath;
449 browseDialog.master = rootWindow;
451 // THIS PART WAS MISSING IN THE PathBox INTEGRATION AND WAS CRUCIAL
452 if(dirBox) dirBox.browsing = true;
453 if(browseDialog.Modal())
455 modifiedDocument = true;
456 OnPathBrowsed(browseDialog.filePath);
457 NotifyModified(master, this);
459 if(dirBox) dirBox.browsing = false;
467 void CheckFileExists()
469 if(typeExpected != none)
471 BitmapResource icon = null;
472 FileAttribs exists = FileExists(editBox.contents);
474 //printf("%s\n", editBox.contents);
478 // TODO: improvements, add drive, etc, also find a better solution/icon for expect any and file doesn't exist
479 icon = exists ? exists.isFile ? file : exists.isDirectory ? folder : null : null;
482 icon = exists && exists.isDirectory ? folder : brokenFolder;
485 icon = exists && exists.isFile ? file : brokenFile;
489 picture.image = icon;
493 void OnRedraw(Surface surface)
497 surface.SetBackground(activeBorder);
498 surface.Area(0, 0, clientSize.w, clientSize.h);
501 Window::OnRedraw(surface);
510 property PathTypeExpected typeExpected
514 if(value != typeExpected)
516 if(value == none || typeExpected == none)
518 bool withIcon = value != none;
519 picture.visible = withIcon;
520 editBox.anchor.left = withIcon ? 18 : 1;
523 typeExpected = value;
524 if(browseDialog && browseDialog.type == open && typeExpected == directory)
525 browseDialog.type = selectDir;
530 property FileDialog browseDialog
535 browseDialog = value;
539 if(browseDialog.type == open && typeExpected == directory)
540 browseDialog.type = selectDir;
541 if(!strcmp(browseDialog.text, "Select a file...") && text)
543 char temp[1024] = "Select ";
546 browseDialog.text = temp;
549 browse.visible = browseDialog ? true : false;
550 editBox.anchor.right = browseDialog ? 26 : 1;
554 void Home() { editBox.Home(); }
555 void End() { editBox.End(); }
557 void SelectAll() { editBox.SelectAll(); }
558 void Deselect() { editBox.Deselect(); }
564 char path[MAX_LOCATION];
565 GetSystemPathBuffer(path, value);
566 editBox.contents = path;
571 get { return editBox.contents; }
573 property String slashPath { get { return GetSlashPathBuffer (path, editBox.contents); } };
574 property String systemPath { get { return GetSystemPathBuffer(path, editBox.contents); } };
576 virtual char * OnBrowse()
578 return editBox.contents;
581 virtual void OnPathBrowsed(char * browsedPath)
583 property::path = browsedPath;
587 virtual bool Window::NotifyModified(PathBox pathBox);