mirror of
https://github.com/gryf/wmaker.git
synced 2026-02-15 13:35:53 +01:00
Initial revision
This commit is contained in:
559
WINGs/wfilepanel.c
Normal file
559
WINGs/wfilepanel.c
Normal file
@@ -0,0 +1,559 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#include "WINGsP.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 1024
|
||||
#endif
|
||||
|
||||
typedef struct W_FilePanel {
|
||||
WMWindow *win;
|
||||
|
||||
WMLabel *iconLabel;
|
||||
WMLabel *titleLabel;
|
||||
|
||||
WMFrame *line;
|
||||
|
||||
WMLabel *nameLabel;
|
||||
WMBrowser *browser;
|
||||
|
||||
WMButton *okButton;
|
||||
WMButton *cancelButton;
|
||||
|
||||
WMButton *homeButton;
|
||||
|
||||
WMTextField *fileField;
|
||||
|
||||
char **fileTypes;
|
||||
|
||||
struct {
|
||||
unsigned int canExit:1;
|
||||
unsigned int canceled:1; /* clicked on cancel */
|
||||
unsigned int done:1;
|
||||
unsigned int filtered:1;
|
||||
unsigned int canChooseFiles:1;
|
||||
unsigned int canChooseDirectories:1;
|
||||
unsigned int showAllFiles:1;
|
||||
unsigned int canFreeFileTypes:1;
|
||||
unsigned int fileMustExist:1;
|
||||
} flags;
|
||||
} W_FilePanel;
|
||||
|
||||
|
||||
#define PWIDTH 320
|
||||
#define PHEIGHT 360
|
||||
|
||||
static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
|
||||
static void browserClick();
|
||||
|
||||
static void fillColumn(WMBrowser *bPtr, int column);
|
||||
|
||||
static void goHome();
|
||||
|
||||
static void buttonClick();
|
||||
|
||||
static char *getCurrentFileName(WMFilePanel *panel);
|
||||
|
||||
static int
|
||||
closestListItem(WMList *list, char *text)
|
||||
{
|
||||
WMListItem *item = WMGetListItem(list, 0);
|
||||
int i = 0;
|
||||
int len = strlen(text);
|
||||
|
||||
if (len==0)
|
||||
return -1;
|
||||
|
||||
while (item) {
|
||||
if (strlen(item->text) >= len && strncmp(item->text, text, len)==0) {
|
||||
return i;
|
||||
}
|
||||
item = item->nextPtr;
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
textChangedObserver(void *observerData, WMNotification *notification)
|
||||
{
|
||||
W_FilePanel *panel = (W_FilePanel*)observerData;
|
||||
char *text;
|
||||
WMList *list;
|
||||
int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
|
||||
int i;
|
||||
|
||||
list = WMGetBrowserListInColumn(panel->browser, col);
|
||||
if (!list)
|
||||
return;
|
||||
text = WMGetTextFieldText(panel->fileField);
|
||||
|
||||
i = closestListItem(list, text);
|
||||
WMSelectListItem(list, i);
|
||||
if (i>=0)
|
||||
WMSetListPosition(list, i);
|
||||
|
||||
free(text);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
textEditedObserver(void *observerData, WMNotification *notification)
|
||||
{
|
||||
W_FilePanel *panel = (W_FilePanel*)observerData;
|
||||
|
||||
if ((int)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
|
||||
WMPerformButtonClick(panel->okButton);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static WMFilePanel*
|
||||
makeFilePanel(WMScreen *scrPtr, char *name, char *title)
|
||||
{
|
||||
WMFilePanel *fPtr;
|
||||
WMFont *largeFont;
|
||||
|
||||
fPtr = wmalloc(sizeof(WMFilePanel));
|
||||
memset(fPtr, 0, sizeof(WMFilePanel));
|
||||
|
||||
fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
|
||||
|WMResizableWindowMask);
|
||||
WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
|
||||
WMSetWindowTitle(fPtr->win, "");
|
||||
|
||||
fPtr->iconLabel = WMCreateLabel(fPtr->win);
|
||||
WMResizeWidget(fPtr->iconLabel, 64, 64);
|
||||
WMMoveWidget(fPtr->iconLabel, 0, 0);
|
||||
WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
|
||||
WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIcon);
|
||||
|
||||
fPtr->titleLabel = WMCreateLabel(fPtr->win);
|
||||
WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
|
||||
WMMoveWidget(fPtr->titleLabel, 64, 0);
|
||||
largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
|
||||
WMSetLabelFont(fPtr->titleLabel, largeFont);
|
||||
WMReleaseFont(largeFont);
|
||||
WMSetLabelText(fPtr->titleLabel, title);
|
||||
|
||||
fPtr->line = WMCreateFrame(fPtr->win);
|
||||
WMMoveWidget(fPtr->line, 0, 64);
|
||||
WMResizeWidget(fPtr->line, PWIDTH, 2);
|
||||
WMSetFrameRelief(fPtr->line, WRGroove);
|
||||
|
||||
fPtr->browser = WMCreateBrowser(fPtr->win);
|
||||
WMSetBrowserFillColumnProc(fPtr->browser, fillColumn);
|
||||
WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
|
||||
WMMoveWidget(fPtr->browser, 7, 72);
|
||||
WMHangData(fPtr->browser, fPtr);
|
||||
|
||||
fPtr->nameLabel = WMCreateLabel(fPtr->win);
|
||||
WMMoveWidget(fPtr->nameLabel, 7, 282);
|
||||
WMResizeWidget(fPtr->nameLabel, 55, 14);
|
||||
WMSetLabelText(fPtr->nameLabel, "Name:");
|
||||
|
||||
fPtr->fileField = WMCreateTextField(fPtr->win);
|
||||
WMMoveWidget(fPtr->fileField, 60, 278);
|
||||
WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
|
||||
WMAddNotificationObserver(textEditedObserver, fPtr,
|
||||
WMTextDidEndEditingNotification,
|
||||
fPtr->fileField);
|
||||
WMAddNotificationObserver(textChangedObserver, fPtr,
|
||||
WMTextDidChangeNotification,
|
||||
fPtr->fileField);
|
||||
|
||||
fPtr->okButton = WMCreateCommandButton(fPtr->win);
|
||||
WMMoveWidget(fPtr->okButton, 230, 325);
|
||||
WMResizeWidget(fPtr->okButton, 80, 28);
|
||||
WMSetButtonText(fPtr->okButton, "OK");
|
||||
WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
|
||||
WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
|
||||
WMSetButtonImagePosition(fPtr->okButton, WIPRight);
|
||||
WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
|
||||
|
||||
fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
|
||||
WMMoveWidget(fPtr->cancelButton, 140, 325);
|
||||
WMResizeWidget(fPtr->cancelButton, 80, 28);
|
||||
WMSetButtonText(fPtr->cancelButton, "Cancel");
|
||||
WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
|
||||
|
||||
fPtr->homeButton = WMCreateCommandButton(fPtr->win);
|
||||
WMMoveWidget(fPtr->homeButton, 55, 325);
|
||||
WMResizeWidget(fPtr->homeButton, 28, 28);
|
||||
WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
|
||||
WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
|
||||
WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
|
||||
|
||||
WMRealizeWidget(fPtr->win);
|
||||
WMMapSubwidgets(fPtr->win);
|
||||
|
||||
WMLoadBrowserColumnZero(fPtr->browser);
|
||||
|
||||
fPtr->flags.canChooseFiles = 1;
|
||||
fPtr->flags.canChooseDirectories = 1;
|
||||
|
||||
return fPtr;
|
||||
}
|
||||
|
||||
|
||||
WMOpenPanel*
|
||||
WMGetOpenPanel(WMScreen *scrPtr)
|
||||
{
|
||||
WMFilePanel *panel;
|
||||
|
||||
if (scrPtr->sharedOpenPanel)
|
||||
return scrPtr->sharedOpenPanel;
|
||||
|
||||
panel = makeFilePanel(scrPtr, "openFilePanel", "Open");
|
||||
panel->flags.fileMustExist = 1;
|
||||
|
||||
scrPtr->sharedOpenPanel = panel;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
WMSavePanel*
|
||||
WMGetSavePanel(WMScreen *scrPtr)
|
||||
{
|
||||
WMFilePanel *panel;
|
||||
|
||||
if (scrPtr->sharedSavePanel)
|
||||
return scrPtr->sharedSavePanel;
|
||||
|
||||
panel = makeFilePanel(scrPtr, "saveFilePanel", "Save");
|
||||
panel->flags.fileMustExist = 0;
|
||||
|
||||
scrPtr->sharedSavePanel = panel;
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMFreeFilePanel(WMFilePanel *panel)
|
||||
{
|
||||
if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
|
||||
WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
|
||||
}
|
||||
WMRemoveNotificationObserver(panel);
|
||||
WMUnmapWidget(panel->win);
|
||||
WMDestroyWidget(panel->win);
|
||||
free(panel);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
WMRunModalSavePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
|
||||
char *path, char *name)
|
||||
{
|
||||
WMScreen *scr = WMWidgetScreen(panel->win);
|
||||
XEvent event;
|
||||
|
||||
WMChangePanelOwner(panel->win, owner);
|
||||
|
||||
WMSetFilePanelDirectory(panel, path);
|
||||
|
||||
panel->flags.done = 0;
|
||||
panel->fileTypes = NULL;
|
||||
|
||||
panel->flags.filtered = 0;
|
||||
|
||||
WMMapWidget(panel->win);
|
||||
|
||||
while (!panel->flags.done) {
|
||||
WMNextEvent(scr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
|
||||
WMCloseWindow(panel->win);
|
||||
|
||||
return (panel->flags.canceled ? False : True);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
WMRunModalOpenPanelForDirectory(WMFilePanel *panel, WMWindow *owner,
|
||||
char *path, char *name, char **fileTypes)
|
||||
{
|
||||
WMScreen *scr = WMWidgetScreen(panel->win);
|
||||
XEvent event;
|
||||
|
||||
WMChangePanelOwner(panel->win, owner);
|
||||
|
||||
WMSetFilePanelDirectory(panel, path);
|
||||
|
||||
panel->flags.done = 0;
|
||||
|
||||
if (fileTypes)
|
||||
panel->flags.filtered = 1;
|
||||
panel->fileTypes = fileTypes;
|
||||
|
||||
WMMapWidget(panel->win);
|
||||
|
||||
while (!panel->flags.done) {
|
||||
WMNextEvent(scr->display, &event);
|
||||
WMHandleEvent(&event);
|
||||
}
|
||||
|
||||
WMCloseWindow(panel->win);
|
||||
|
||||
return (panel->flags.canceled ? False : True);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
|
||||
{
|
||||
WMList *list;
|
||||
WMListItem *item;
|
||||
int col;
|
||||
|
||||
WMSetBrowserPath(panel->browser, path);
|
||||
col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
|
||||
list = WMGetBrowserListInColumn(panel->browser, col);
|
||||
if (list && (item = WMGetListSelectedItem(list))) {
|
||||
if (item->isBranch) {
|
||||
WMSetTextFieldText(panel->fileField, NULL);
|
||||
} else {
|
||||
WMSetTextFieldText(panel->fileField, item->text);
|
||||
}
|
||||
} else {
|
||||
WMSetTextFieldText(panel->fileField, path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, int flag)
|
||||
{
|
||||
panel->flags.canChooseDirectories = flag;
|
||||
}
|
||||
|
||||
void
|
||||
WMSetFilePanelCanChooseFiles(WMFilePanel *panel, int flag)
|
||||
{
|
||||
panel->flags.canChooseFiles = flag;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
WMGetFilePanelFileName(WMFilePanel *panel)
|
||||
{
|
||||
return getCurrentFileName(panel);
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
get_name_from_path(char *path)
|
||||
{
|
||||
int size;
|
||||
|
||||
assert(path!=NULL);
|
||||
|
||||
size = strlen(path);
|
||||
|
||||
/* remove trailing / */
|
||||
while (size > 0 && path[size-1]=='/')
|
||||
size--;
|
||||
/* directory was root */
|
||||
if (size == 0)
|
||||
return wstrdup("/");
|
||||
|
||||
while (size > 0 && path[size-1] != '/')
|
||||
size--;
|
||||
|
||||
return wstrdup(&(path[size]));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
|
||||
{
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
|
||||
{
|
||||
WMBrowser *bPtr = panel->browser;
|
||||
struct dirent *dentry;
|
||||
DIR *dir;
|
||||
struct stat stat_buf;
|
||||
char pbuf[PATH_MAX+16];
|
||||
|
||||
assert(column >= 0);
|
||||
assert(path != NULL);
|
||||
|
||||
/* put directory name in the title */
|
||||
WMSetBrowserColumnTitle(bPtr, column, get_name_from_path(path));
|
||||
|
||||
dir = opendir(path);
|
||||
|
||||
if (!dir) {
|
||||
#ifdef VERBOSE
|
||||
printf("WINGs: could not open directory %s\n", path);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* list contents in the column */
|
||||
while ((dentry = readdir(dir))) {
|
||||
if (strcmp(dentry->d_name, ".")==0 ||
|
||||
strcmp(dentry->d_name, "..")==0)
|
||||
continue;
|
||||
|
||||
strcpy(pbuf, path);
|
||||
if (strcmp(path, "/")!=0)
|
||||
strcat(pbuf, "/");
|
||||
strcat(pbuf, dentry->d_name);
|
||||
|
||||
if (stat(pbuf, &stat_buf)!=0) {
|
||||
#ifdef VERBOSE
|
||||
printf("WINGs: could not stat %s\n", pbuf);
|
||||
#endif
|
||||
continue;
|
||||
} else {
|
||||
int isDirectory;
|
||||
|
||||
isDirectory = S_ISDIR(stat_buf.st_mode);
|
||||
|
||||
if (filterFileName(panel, dentry->d_name, isDirectory))
|
||||
WMAddSortedBrowserItem(bPtr, column, dentry->d_name,
|
||||
isDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fillColumn(WMBrowser *bPtr, int column)
|
||||
{
|
||||
char *path;
|
||||
WMFilePanel *panel;
|
||||
|
||||
if (column > 0) {
|
||||
path = WMGetBrowserPathToColumn(bPtr, column-1);
|
||||
} else {
|
||||
path = wstrdup("/");
|
||||
}
|
||||
|
||||
panel = WMGetHangedData(bPtr);
|
||||
listDirectoryOnColumn(panel, column, path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
browserClick(WMBrowser *bPtr, WMFilePanel *panel)
|
||||
{
|
||||
int col = WMGetBrowserSelectedColumn(bPtr);
|
||||
WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
|
||||
|
||||
if (!item || item->isBranch)
|
||||
WMSetTextFieldText(panel->fileField, NULL);
|
||||
else {
|
||||
WMSetTextFieldText(panel->fileField, item->text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
goHome(WMButton *bPtr, WMFilePanel *panel)
|
||||
{
|
||||
char *home;
|
||||
|
||||
/* home is statically allocated. Don't free it! */
|
||||
home = wgethomedir();
|
||||
if (!home)
|
||||
return;
|
||||
|
||||
WMSetFilePanelDirectory(panel, home);
|
||||
}
|
||||
|
||||
|
||||
static char*
|
||||
getCurrentFileName(WMFilePanel *panel)
|
||||
{
|
||||
char *path;
|
||||
char *file;
|
||||
char *tmp;
|
||||
int len;
|
||||
|
||||
path = WMGetBrowserPath(panel->browser);
|
||||
|
||||
len = strlen(path);
|
||||
if (path[len-1]=='/') {
|
||||
file = WMGetTextFieldText(panel->fileField);
|
||||
tmp = wmalloc(strlen(path)+strlen(file)+8);
|
||||
strcpy(tmp, path);
|
||||
strcat(tmp, file);
|
||||
free(file);
|
||||
free(path);
|
||||
return tmp;
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Bool
|
||||
validOpenFile(WMFilePanel *panel)
|
||||
{
|
||||
WMListItem *item;
|
||||
int col;
|
||||
|
||||
col = WMGetBrowserSelectedColumn(panel->browser);
|
||||
item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
|
||||
if (item) {
|
||||
if (item->isBranch && !panel->flags.canChooseDirectories)
|
||||
return False;
|
||||
else if (!item->isBranch && !panel->flags.canChooseFiles)
|
||||
return False;
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
buttonClick(WMButton *bPtr, WMFilePanel *panel)
|
||||
{
|
||||
if (bPtr == panel->okButton) {
|
||||
if (panel->flags.fileMustExist) {
|
||||
char *file;
|
||||
if (!validOpenFile(panel))
|
||||
return;
|
||||
|
||||
file = getCurrentFileName(panel);
|
||||
if (access(file, F_OK)!=0) {
|
||||
WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
|
||||
"Error", "File does not exist.",
|
||||
"Ok", NULL, NULL);
|
||||
free(file);
|
||||
return;
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
panel->flags.canceled = 0;
|
||||
} else
|
||||
panel->flags.canceled = 1;
|
||||
|
||||
panel->flags.done = 1;
|
||||
}
|
||||
Reference in New Issue
Block a user