17 typedef struct W_FilePanel
{
29 WMButton
*cancelButton
;
33 WMView
*accessoryView
;
35 WMTextField
*fileField
;
40 unsigned int canExit
:1;
41 unsigned int canceled
:1; /* clicked on cancel */
43 unsigned int filtered
:1;
44 unsigned int canChooseFiles
:1;
45 unsigned int canChooseDirectories
:1;
46 unsigned int showAllFiles
:1;
47 unsigned int canFreeFileTypes
:1;
48 unsigned int fileMustExist
:1;
56 static void listDirectoryOnColumn(WMFilePanel
*panel
, int column
, char *path
);
57 static void browserClick();
59 static void fillColumn(WMBrowser
*bPtr
, int column
);
63 static void buttonClick();
65 static char *getCurrentFileName(WMFilePanel
*panel
);
68 closestListItem(WMList
*list
, char *text
)
70 WMListItem
*item
= WMGetListItem(list
, 0);
72 int len
= strlen(text
);
78 if (strlen(item
->text
) >= len
&& strncmp(item
->text
, text
, len
)==0) {
89 textChangedObserver(void *observerData
, WMNotification
*notification
)
91 W_FilePanel
*panel
= (W_FilePanel
*)observerData
;
94 int col
= WMGetBrowserNumberOfColumns(panel
->browser
) - 1;
97 list
= WMGetBrowserListInColumn(panel
->browser
, col
);
100 text
= WMGetTextFieldText(panel
->fileField
);
102 i
= closestListItem(list
, text
);
103 WMSelectListItem(list
, i
);
105 WMSetListPosition(list
, i
);
112 textEditedObserver(void *observerData
, WMNotification
*notification
)
114 W_FilePanel
*panel
= (W_FilePanel
*)observerData
;
116 if ((int)WMGetNotificationClientData(notification
)==WMReturnTextMovement
) {
117 WMPerformButtonClick(panel
->okButton
);
124 makeFilePanel(WMScreen
*scrPtr
, char *name
, char *title
)
129 fPtr
= wmalloc(sizeof(WMFilePanel
));
130 memset(fPtr
, 0, sizeof(WMFilePanel
));
132 fPtr
->win
= WMCreateWindowWithStyle(scrPtr
, name
, WMTitledWindowMask
133 |WMResizableWindowMask
);
134 WMResizeWidget(fPtr
->win
, PWIDTH
, PHEIGHT
);
135 WMSetWindowTitle(fPtr
->win
, "");
137 fPtr
->iconLabel
= WMCreateLabel(fPtr
->win
);
138 WMResizeWidget(fPtr
->iconLabel
, 64, 64);
139 WMMoveWidget(fPtr
->iconLabel
, 0, 0);
140 WMSetLabelImagePosition(fPtr
->iconLabel
, WIPImageOnly
);
141 WMSetLabelImage(fPtr
->iconLabel
, scrPtr
->applicationIcon
);
143 fPtr
->titleLabel
= WMCreateLabel(fPtr
->win
);
144 WMResizeWidget(fPtr
->titleLabel
, PWIDTH
-64, 64);
145 WMMoveWidget(fPtr
->titleLabel
, 64, 0);
146 largeFont
= WMBoldSystemFontOfSize(scrPtr
, 24);
147 WMSetLabelFont(fPtr
->titleLabel
, largeFont
);
148 WMReleaseFont(largeFont
);
149 WMSetLabelText(fPtr
->titleLabel
, title
);
151 fPtr
->line
= WMCreateFrame(fPtr
->win
);
152 WMMoveWidget(fPtr
->line
, 0, 64);
153 WMResizeWidget(fPtr
->line
, PWIDTH
, 2);
154 WMSetFrameRelief(fPtr
->line
, WRGroove
);
156 fPtr
->browser
= WMCreateBrowser(fPtr
->win
);
157 WMSetBrowserFillColumnProc(fPtr
->browser
, fillColumn
);
158 WMSetBrowserAction(fPtr
->browser
, browserClick
, fPtr
);
159 WMMoveWidget(fPtr
->browser
, 7, 72);
160 WMHangData(fPtr
->browser
, fPtr
);
162 fPtr
->nameLabel
= WMCreateLabel(fPtr
->win
);
163 WMMoveWidget(fPtr
->nameLabel
, 7, 282);
164 WMResizeWidget(fPtr
->nameLabel
, 55, 14);
165 WMSetLabelText(fPtr
->nameLabel
, "Name:");
167 fPtr
->fileField
= WMCreateTextField(fPtr
->win
);
168 WMMoveWidget(fPtr
->fileField
, 60, 278);
169 WMResizeWidget(fPtr
->fileField
, PWIDTH
-60-10, 24);
170 WMAddNotificationObserver(textEditedObserver
, fPtr
,
171 WMTextDidEndEditingNotification
,
173 WMAddNotificationObserver(textChangedObserver
, fPtr
,
174 WMTextDidChangeNotification
,
177 fPtr
->okButton
= WMCreateCommandButton(fPtr
->win
);
178 WMMoveWidget(fPtr
->okButton
, 230, 325);
179 WMResizeWidget(fPtr
->okButton
, 80, 28);
180 WMSetButtonText(fPtr
->okButton
, "OK");
181 WMSetButtonImage(fPtr
->okButton
, scrPtr
->buttonArrow
);
182 WMSetButtonAltImage(fPtr
->okButton
, scrPtr
->pushedButtonArrow
);
183 WMSetButtonImagePosition(fPtr
->okButton
, WIPRight
);
184 WMSetButtonAction(fPtr
->okButton
, buttonClick
, fPtr
);
186 fPtr
->cancelButton
= WMCreateCommandButton(fPtr
->win
);
187 WMMoveWidget(fPtr
->cancelButton
, 140, 325);
188 WMResizeWidget(fPtr
->cancelButton
, 80, 28);
189 WMSetButtonText(fPtr
->cancelButton
, "Cancel");
190 WMSetButtonAction(fPtr
->cancelButton
, buttonClick
, fPtr
);
192 fPtr
->homeButton
= WMCreateCommandButton(fPtr
->win
);
193 WMMoveWidget(fPtr
->homeButton
, 55, 325);
194 WMResizeWidget(fPtr
->homeButton
, 28, 28);
195 WMSetButtonImagePosition(fPtr
->homeButton
, WIPImageOnly
);
196 WMSetButtonImage(fPtr
->homeButton
, scrPtr
->homeIcon
);
197 WMSetButtonAltImage(fPtr
->homeButton
, scrPtr
->homeAltIcon
);
198 WMSetButtonAction(fPtr
->homeButton
, goHome
, fPtr
);
200 WMRealizeWidget(fPtr
->win
);
201 WMMapSubwidgets(fPtr
->win
);
203 WMLoadBrowserColumnZero(fPtr
->browser
);
205 fPtr
->flags
.canChooseFiles
= 1;
206 fPtr
->flags
.canChooseDirectories
= 1;
213 WMGetOpenPanel(WMScreen
*scrPtr
)
217 if (scrPtr
->sharedOpenPanel
)
218 return scrPtr
->sharedOpenPanel
;
220 panel
= makeFilePanel(scrPtr
, "openFilePanel", "Open");
221 panel
->flags
.fileMustExist
= 1;
223 scrPtr
->sharedOpenPanel
= panel
;
230 WMGetSavePanel(WMScreen
*scrPtr
)
234 if (scrPtr
->sharedSavePanel
)
235 return scrPtr
->sharedSavePanel
;
237 panel
= makeFilePanel(scrPtr
, "saveFilePanel", "Save");
238 panel
->flags
.fileMustExist
= 0;
240 scrPtr
->sharedSavePanel
= panel
;
247 WMFreeFilePanel(WMFilePanel
*panel
)
249 if (panel
== WMWidgetScreen(panel
->win
)->sharedSavePanel
) {
250 WMWidgetScreen(panel
->win
)->sharedSavePanel
= NULL
;
252 if (panel
== WMWidgetScreen(panel
->win
)->sharedOpenPanel
) {
253 WMWidgetScreen(panel
->win
)->sharedOpenPanel
= NULL
;
255 WMRemoveNotificationObserver(panel
);
256 WMUnmapWidget(panel
->win
);
257 WMDestroyWidget(panel
->win
);
263 WMRunModalSavePanelForDirectory(WMFilePanel
*panel
, WMWindow
*owner
,
264 char *path
, char *name
)
266 WMScreen
*scr
= WMWidgetScreen(panel
->win
);
269 WMChangePanelOwner(panel
->win
, owner
);
271 WMSetFilePanelDirectory(panel
, path
);
273 panel
->flags
.done
= 0;
274 panel
->fileTypes
= NULL
;
276 panel
->flags
.filtered
= 0;
278 WMMapWidget(panel
->win
);
280 while (!panel
->flags
.done
) {
281 WMNextEvent(scr
->display
, &event
);
282 WMHandleEvent(&event
);
285 /* Must withdraw window because the next time we map
286 * it, it might have a different transient owner.
288 WMCloseWindow(panel
->win
);
290 return (panel
->flags
.canceled
? False
: True
);
296 WMRunModalOpenPanelForDirectory(WMFilePanel
*panel
, WMWindow
*owner
,
297 char *path
, char *name
, char **fileTypes
)
299 WMScreen
*scr
= WMWidgetScreen(panel
->win
);
302 WMChangePanelOwner(panel
->win
, owner
);
304 WMSetFilePanelDirectory(panel
, path
);
306 panel
->flags
.done
= 0;
309 panel
->flags
.filtered
= 1;
310 panel
->fileTypes
= fileTypes
;
312 WMMapWidget(panel
->win
);
314 while (!panel
->flags
.done
) {
315 WMNextEvent(scr
->display
, &event
);
316 WMHandleEvent(&event
);
319 WMCloseWindow(panel
->win
);
321 return (panel
->flags
.canceled
? False
: True
);
326 WMSetFilePanelDirectory(WMFilePanel
*panel
, char *path
)
332 WMSetBrowserPath(panel
->browser
, path
);
333 col
= WMGetBrowserNumberOfColumns(panel
->browser
) - 1;
334 list
= WMGetBrowserListInColumn(panel
->browser
, col
);
335 if (list
&& (item
= WMGetListSelectedItem(list
))) {
336 if (item
->isBranch
) {
337 WMSetTextFieldText(panel
->fileField
, NULL
);
339 WMSetTextFieldText(panel
->fileField
, item
->text
);
342 WMSetTextFieldText(panel
->fileField
, path
);
348 WMSetFilePanelCanChooseDirectories(WMFilePanel
*panel
, int flag
)
350 panel
->flags
.canChooseDirectories
= flag
;
354 WMSetFilePanelCanChooseFiles(WMFilePanel
*panel
, int flag
)
356 panel
->flags
.canChooseFiles
= flag
;
361 WMGetFilePanelFileName(WMFilePanel
*panel
)
363 return getCurrentFileName(panel
);
368 WMSetFilePanelAccessoryView(WMFilePanel
*panel
, WMView
*view
)
372 panel
->accessoryView
= view
;
374 v
= WMWidgetView(panel
->win
);
376 W_ReparentView(view
, v
);
378 W_MoveView(view
, (v
->size
.width
- v
->size
.width
)/2, 300);
383 WMGetFilePanelAccessoryView(WMFilePanel
*panel
)
385 return panel
->accessoryView
;
390 get_name_from_path(char *path
)
398 /* remove trailing / */
399 while (size
> 0 && path
[size
-1]=='/')
401 /* directory was root */
405 while (size
> 0 && path
[size
-1] != '/')
408 return wstrdup(&(path
[size
]));
413 filterFileName(WMFilePanel
*panel
, char *file
, Bool isDirectory
)
420 listDirectoryOnColumn(WMFilePanel
*panel
, int column
, char *path
)
422 WMBrowser
*bPtr
= panel
->browser
;
423 struct dirent
*dentry
;
425 struct stat stat_buf
;
426 char pbuf
[PATH_MAX
+16];
429 assert(path
!= NULL
);
431 /* put directory name in the title */
432 WMSetBrowserColumnTitle(bPtr
, column
, get_name_from_path(path
));
438 printf("WINGs: could not open directory %s\n", path
);
443 /* list contents in the column */
444 while ((dentry
= readdir(dir
))) {
445 if (strcmp(dentry
->d_name
, ".")==0 ||
446 strcmp(dentry
->d_name
, "..")==0)
450 if (strcmp(path
, "/")!=0)
452 strcat(pbuf
, dentry
->d_name
);
454 if (stat(pbuf
, &stat_buf
)!=0) {
456 printf("WINGs: could not stat %s\n", pbuf
);
462 isDirectory
= S_ISDIR(stat_buf
.st_mode
);
464 if (filterFileName(panel
, dentry
->d_name
, isDirectory
))
465 WMAddSortedBrowserItem(bPtr
, column
, dentry
->d_name
,
475 fillColumn(WMBrowser
*bPtr
, int column
)
481 path
= WMGetBrowserPathToColumn(bPtr
, column
-1);
486 panel
= WMGetHangedData(bPtr
);
487 listDirectoryOnColumn(panel
, column
, path
);
494 browserClick(WMBrowser
*bPtr
, WMFilePanel
*panel
)
496 int col
= WMGetBrowserSelectedColumn(bPtr
);
497 WMListItem
*item
= WMGetBrowserSelectedItemInColumn(bPtr
, col
);
499 if (!item
|| item
->isBranch
)
500 WMSetTextFieldText(panel
->fileField
, NULL
);
502 WMSetTextFieldText(panel
->fileField
, item
->text
);
508 goHome(WMButton
*bPtr
, WMFilePanel
*panel
)
512 /* home is statically allocated. Don't free it! */
513 home
= wgethomedir();
517 WMSetFilePanelDirectory(panel
, home
);
522 getCurrentFileName(WMFilePanel
*panel
)
529 path
= WMGetBrowserPath(panel
->browser
);
532 if (path
[len
-1]=='/') {
533 file
= WMGetTextFieldText(panel
->fileField
);
534 tmp
= wmalloc(strlen(path
)+strlen(file
)+8);
552 validOpenFile(WMFilePanel
*panel
)
557 col
= WMGetBrowserSelectedColumn(panel
->browser
);
558 item
= WMGetBrowserSelectedItemInColumn(panel
->browser
, col
);
560 if (item
->isBranch
&& !panel
->flags
.canChooseDirectories
)
562 else if (!item
->isBranch
&& !panel
->flags
.canChooseFiles
)
571 buttonClick(WMButton
*bPtr
, WMFilePanel
*panel
)
573 if (bPtr
== panel
->okButton
) {
574 if (panel
->flags
.fileMustExist
) {
576 if (!validOpenFile(panel
))
579 file
= getCurrentFileName(panel
);
580 if (access(file
, F_OK
)!=0) {
581 WMRunAlertPanel(WMWidgetScreen(panel
->win
), panel
->win
,
582 "Error", "File does not exist.",
589 panel
->flags
.canceled
= 0;
591 panel
->flags
.canceled
= 1;
593 panel
->flags
.done
= 1;