1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-30 18:32:34 +01:00
Files
wmaker/WINGs/wfilepanel.c
dan 0261c32636 Code update for Window Maker version 0.50.0
Read changes in ChangeLog and NEWS
1999-01-06 15:22:33 +00:00

593 lines
13 KiB
C

#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;
WMView *accessoryView;
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)->sharedSavePanel) {
WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
}
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);
}
void
WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view)
{
WMView *v;
panel->accessoryView = view;
v = WMWidgetView(panel->win);
W_ReparentView(view, v);
W_MoveView(view, (v->size.width - v->size.width)/2, 300);
}
WMView*
WMGetFilePanelAccessoryView(WMFilePanel *panel)
{
return panel->accessoryView;
}
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);
if (file[0]!='/') {
strcpy(tmp, path);
strcat(tmp, file);
} else
strcpy(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;
}