17 typedef struct W_FilePanel
{
29 WMButton
*cancelButton
;
33 WMTextField
*fileField
;
38 unsigned int canExit
:1;
39 unsigned int canceled
:1; /* clicked on cancel */
41 unsigned int filtered
:1;
42 unsigned int canChooseFiles
:1;
43 unsigned int canChooseDirectories
:1;
44 unsigned int showAllFiles
:1;
45 unsigned int canFreeFileTypes
:1;
46 unsigned int fileMustExist
:1;
54 static void listDirectoryOnColumn(WMFilePanel
*panel
, int column
, char *path
);
55 static void browserClick();
57 static void fillColumn(WMBrowser
*bPtr
, int column
);
61 static void buttonClick();
63 static char *getCurrentFileName(WMFilePanel
*panel
);
66 closestListItem(WMList
*list
, char *text
)
68 WMListItem
*item
= WMGetListItem(list
, 0);
70 int len
= strlen(text
);
76 if (strlen(item
->text
) >= len
&& strncmp(item
->text
, text
, len
)==0) {
87 textChangedObserver(void *observerData
, WMNotification
*notification
)
89 W_FilePanel
*panel
= (W_FilePanel
*)observerData
;
92 int col
= WMGetBrowserNumberOfColumns(panel
->browser
) - 1;
95 list
= WMGetBrowserListInColumn(panel
->browser
, col
);
98 text
= WMGetTextFieldText(panel
->fileField
);
100 i
= closestListItem(list
, text
);
101 WMSelectListItem(list
, i
);
103 WMSetListPosition(list
, i
);
110 textEditedObserver(void *observerData
, WMNotification
*notification
)
112 W_FilePanel
*panel
= (W_FilePanel
*)observerData
;
114 if ((int)WMGetNotificationClientData(notification
)==WMReturnTextMovement
) {
115 WMPerformButtonClick(panel
->okButton
);
122 makeFilePanel(WMScreen
*scrPtr
, char *name
, char *title
)
127 fPtr
= wmalloc(sizeof(WMFilePanel
));
128 memset(fPtr
, 0, sizeof(WMFilePanel
));
130 fPtr
->win
= WMCreateWindowWithStyle(scrPtr
, name
, WMTitledWindowMask
131 |WMResizableWindowMask
);
132 WMResizeWidget(fPtr
->win
, PWIDTH
, PHEIGHT
);
133 WMSetWindowTitle(fPtr
->win
, "");
135 fPtr
->iconLabel
= WMCreateLabel(fPtr
->win
);
136 WMResizeWidget(fPtr
->iconLabel
, 64, 64);
137 WMMoveWidget(fPtr
->iconLabel
, 0, 0);
138 WMSetLabelImagePosition(fPtr
->iconLabel
, WIPImageOnly
);
139 WMSetLabelImage(fPtr
->iconLabel
, scrPtr
->applicationIcon
);
141 fPtr
->titleLabel
= WMCreateLabel(fPtr
->win
);
142 WMResizeWidget(fPtr
->titleLabel
, PWIDTH
-64, 64);
143 WMMoveWidget(fPtr
->titleLabel
, 64, 0);
144 largeFont
= WMBoldSystemFontOfSize(scrPtr
, 24);
145 WMSetLabelFont(fPtr
->titleLabel
, largeFont
);
146 WMReleaseFont(largeFont
);
147 WMSetLabelText(fPtr
->titleLabel
, title
);
149 fPtr
->line
= WMCreateFrame(fPtr
->win
);
150 WMMoveWidget(fPtr
->line
, 0, 64);
151 WMResizeWidget(fPtr
->line
, PWIDTH
, 2);
152 WMSetFrameRelief(fPtr
->line
, WRGroove
);
154 fPtr
->browser
= WMCreateBrowser(fPtr
->win
);
155 WMSetBrowserFillColumnProc(fPtr
->browser
, fillColumn
);
156 WMSetBrowserAction(fPtr
->browser
, browserClick
, fPtr
);
157 WMMoveWidget(fPtr
->browser
, 7, 72);
158 WMHangData(fPtr
->browser
, fPtr
);
160 fPtr
->nameLabel
= WMCreateLabel(fPtr
->win
);
161 WMMoveWidget(fPtr
->nameLabel
, 7, 282);
162 WMResizeWidget(fPtr
->nameLabel
, 55, 14);
163 WMSetLabelText(fPtr
->nameLabel
, "Name:");
165 fPtr
->fileField
= WMCreateTextField(fPtr
->win
);
166 WMMoveWidget(fPtr
->fileField
, 60, 278);
167 WMResizeWidget(fPtr
->fileField
, PWIDTH
-60-10, 24);
168 WMAddNotificationObserver(textEditedObserver
, fPtr
,
169 WMTextDidEndEditingNotification
,
171 WMAddNotificationObserver(textChangedObserver
, fPtr
,
172 WMTextDidChangeNotification
,
175 fPtr
->okButton
= WMCreateCommandButton(fPtr
->win
);
176 WMMoveWidget(fPtr
->okButton
, 230, 325);
177 WMResizeWidget(fPtr
->okButton
, 80, 28);
178 WMSetButtonText(fPtr
->okButton
, "OK");
179 WMSetButtonImage(fPtr
->okButton
, scrPtr
->buttonArrow
);
180 WMSetButtonAltImage(fPtr
->okButton
, scrPtr
->pushedButtonArrow
);
181 WMSetButtonImagePosition(fPtr
->okButton
, WIPRight
);
182 WMSetButtonAction(fPtr
->okButton
, buttonClick
, fPtr
);
184 fPtr
->cancelButton
= WMCreateCommandButton(fPtr
->win
);
185 WMMoveWidget(fPtr
->cancelButton
, 140, 325);
186 WMResizeWidget(fPtr
->cancelButton
, 80, 28);
187 WMSetButtonText(fPtr
->cancelButton
, "Cancel");
188 WMSetButtonAction(fPtr
->cancelButton
, buttonClick
, fPtr
);
190 fPtr
->homeButton
= WMCreateCommandButton(fPtr
->win
);
191 WMMoveWidget(fPtr
->homeButton
, 55, 325);
192 WMResizeWidget(fPtr
->homeButton
, 28, 28);
193 WMSetButtonImagePosition(fPtr
->homeButton
, WIPImageOnly
);
194 WMSetButtonImage(fPtr
->homeButton
, scrPtr
->homeIcon
);
195 WMSetButtonAction(fPtr
->homeButton
, goHome
, fPtr
);
197 WMRealizeWidget(fPtr
->win
);
198 WMMapSubwidgets(fPtr
->win
);
200 WMLoadBrowserColumnZero(fPtr
->browser
);
202 fPtr
->flags
.canChooseFiles
= 1;
203 fPtr
->flags
.canChooseDirectories
= 1;
210 WMGetOpenPanel(WMScreen
*scrPtr
)
214 if (scrPtr
->sharedOpenPanel
)
215 return scrPtr
->sharedOpenPanel
;
217 panel
= makeFilePanel(scrPtr
, "openFilePanel", "Open");
218 panel
->flags
.fileMustExist
= 1;
220 scrPtr
->sharedOpenPanel
= panel
;
227 WMGetSavePanel(WMScreen
*scrPtr
)
231 if (scrPtr
->sharedSavePanel
)
232 return scrPtr
->sharedSavePanel
;
234 panel
= makeFilePanel(scrPtr
, "saveFilePanel", "Save");
235 panel
->flags
.fileMustExist
= 0;
237 scrPtr
->sharedSavePanel
= panel
;
244 WMFreeFilePanel(WMFilePanel
*panel
)
246 if (panel
== WMWidgetScreen(panel
->win
)->sharedSavePanel
) {
247 WMWidgetScreen(panel
->win
)->sharedSavePanel
= NULL
;
249 if (panel
== WMWidgetScreen(panel
->win
)->sharedOpenPanel
) {
250 WMWidgetScreen(panel
->win
)->sharedOpenPanel
= NULL
;
252 WMRemoveNotificationObserver(panel
);
253 WMUnmapWidget(panel
->win
);
254 WMDestroyWidget(panel
->win
);
260 WMRunModalSavePanelForDirectory(WMFilePanel
*panel
, WMWindow
*owner
,
261 char *path
, char *name
)
263 WMScreen
*scr
= WMWidgetScreen(panel
->win
);
266 WMChangePanelOwner(panel
->win
, owner
);
268 WMSetFilePanelDirectory(panel
, path
);
270 panel
->flags
.done
= 0;
271 panel
->fileTypes
= NULL
;
273 panel
->flags
.filtered
= 0;
275 WMMapWidget(panel
->win
);
277 while (!panel
->flags
.done
) {
278 WMNextEvent(scr
->display
, &event
);
279 WMHandleEvent(&event
);
282 WMCloseWindow(panel
->win
);
284 return (panel
->flags
.canceled
? False
: True
);
290 WMRunModalOpenPanelForDirectory(WMFilePanel
*panel
, WMWindow
*owner
,
291 char *path
, char *name
, char **fileTypes
)
293 WMScreen
*scr
= WMWidgetScreen(panel
->win
);
296 WMChangePanelOwner(panel
->win
, owner
);
298 WMSetFilePanelDirectory(panel
, path
);
300 panel
->flags
.done
= 0;
303 panel
->flags
.filtered
= 1;
304 panel
->fileTypes
= fileTypes
;
306 WMMapWidget(panel
->win
);
308 while (!panel
->flags
.done
) {
309 WMNextEvent(scr
->display
, &event
);
310 WMHandleEvent(&event
);
313 WMCloseWindow(panel
->win
);
315 return (panel
->flags
.canceled
? False
: True
);
320 WMSetFilePanelDirectory(WMFilePanel
*panel
, char *path
)
326 WMSetBrowserPath(panel
->browser
, path
);
327 col
= WMGetBrowserNumberOfColumns(panel
->browser
) - 1;
328 list
= WMGetBrowserListInColumn(panel
->browser
, col
);
329 if (list
&& (item
= WMGetListSelectedItem(list
))) {
330 if (item
->isBranch
) {
331 WMSetTextFieldText(panel
->fileField
, NULL
);
333 WMSetTextFieldText(panel
->fileField
, item
->text
);
336 WMSetTextFieldText(panel
->fileField
, path
);
342 WMSetFilePanelCanChooseDirectories(WMFilePanel
*panel
, int flag
)
344 panel
->flags
.canChooseDirectories
= flag
;
348 WMSetFilePanelCanChooseFiles(WMFilePanel
*panel
, int flag
)
350 panel
->flags
.canChooseFiles
= flag
;
355 WMGetFilePanelFileName(WMFilePanel
*panel
)
357 return getCurrentFileName(panel
);
362 get_name_from_path(char *path
)
370 /* remove trailing / */
371 while (size
> 0 && path
[size
-1]=='/')
373 /* directory was root */
377 while (size
> 0 && path
[size
-1] != '/')
380 return wstrdup(&(path
[size
]));
385 filterFileName(WMFilePanel
*panel
, char *file
, Bool isDirectory
)
392 listDirectoryOnColumn(WMFilePanel
*panel
, int column
, char *path
)
394 WMBrowser
*bPtr
= panel
->browser
;
395 struct dirent
*dentry
;
397 struct stat stat_buf
;
398 char pbuf
[PATH_MAX
+16];
401 assert(path
!= NULL
);
403 /* put directory name in the title */
404 WMSetBrowserColumnTitle(bPtr
, column
, get_name_from_path(path
));
410 printf("WINGs: could not open directory %s\n", path
);
415 /* list contents in the column */
416 while ((dentry
= readdir(dir
))) {
417 if (strcmp(dentry
->d_name
, ".")==0 ||
418 strcmp(dentry
->d_name
, "..")==0)
422 if (strcmp(path
, "/")!=0)
424 strcat(pbuf
, dentry
->d_name
);
426 if (stat(pbuf
, &stat_buf
)!=0) {
428 printf("WINGs: could not stat %s\n", pbuf
);
434 isDirectory
= S_ISDIR(stat_buf
.st_mode
);
436 if (filterFileName(panel
, dentry
->d_name
, isDirectory
))
437 WMAddSortedBrowserItem(bPtr
, column
, dentry
->d_name
,
447 fillColumn(WMBrowser
*bPtr
, int column
)
453 path
= WMGetBrowserPathToColumn(bPtr
, column
-1);
458 panel
= WMGetHangedData(bPtr
);
459 listDirectoryOnColumn(panel
, column
, path
);
466 browserClick(WMBrowser
*bPtr
, WMFilePanel
*panel
)
468 int col
= WMGetBrowserSelectedColumn(bPtr
);
469 WMListItem
*item
= WMGetBrowserSelectedItemInColumn(bPtr
, col
);
471 if (!item
|| item
->isBranch
)
472 WMSetTextFieldText(panel
->fileField
, NULL
);
474 WMSetTextFieldText(panel
->fileField
, item
->text
);
480 goHome(WMButton
*bPtr
, WMFilePanel
*panel
)
484 /* home is statically allocated. Don't free it! */
485 home
= wgethomedir();
489 WMSetFilePanelDirectory(panel
, home
);
494 getCurrentFileName(WMFilePanel
*panel
)
501 path
= WMGetBrowserPath(panel
->browser
);
504 if (path
[len
-1]=='/') {
505 file
= WMGetTextFieldText(panel
->fileField
);
506 tmp
= wmalloc(strlen(path
)+strlen(file
)+8);
524 validOpenFile(WMFilePanel
*panel
)
529 col
= WMGetBrowserSelectedColumn(panel
->browser
);
530 item
= WMGetBrowserSelectedItemInColumn(panel
->browser
, col
);
532 if (item
->isBranch
&& !panel
->flags
.canChooseDirectories
)
534 else if (!item
->isBranch
&& !panel
->flags
.canChooseFiles
)
543 buttonClick(WMButton
*bPtr
, WMFilePanel
*panel
)
545 if (bPtr
== panel
->okButton
) {
546 if (panel
->flags
.fileMustExist
) {
548 if (!validOpenFile(panel
))
551 file
= getCurrentFileName(panel
);
552 if (access(file
, F_OK
)!=0) {
553 WMRunAlertPanel(WMWidgetScreen(panel
->win
), panel
->win
,
554 "Error", "File does not exist.",
561 panel
->flags
.canceled
= 0;
563 panel
->flags
.canceled
= 1;
565 panel
->flags
.done
= 1;