aseprite/src/dialogs/filesel.cpp

538 lines
15 KiB
C++
Raw Normal View History

2007-11-17 02:25:45 +08:00
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2008 David A. Capello
2007-09-19 07:57:02 +08:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <cassert>
#include <vector>
2007-09-19 07:57:02 +08:00
#include <allegro.h>
#include <allegro/internal/aintern.h>
#include <errno.h>
#include "jinete/jinete.h"
2007-09-19 07:57:02 +08:00
#include "core/app.h"
2007-09-19 07:57:02 +08:00
#include "core/cfg.h"
#include "core/dirs.h"
#include "file/file.h"
2007-09-19 07:57:02 +08:00
#include "modules/gfx.h"
#include "modules/gui.h"
#include "widgets/fileview.h"
2007-09-19 07:57:02 +08:00
#if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0')
# define HAVE_DRIVES
#endif
#ifndef MAX_PATH
# define MAX_PATH 4096 /* TODO this is needed for Linux, is it correct? */
#endif
/* Variables used only to maintain the history of navigation. */
static JLink navigation_position = NULL; /* current position in the navigation history */
static JList navigation_history = NULL; /* set of FileItems navigated */
static bool navigation_locked = FALSE; /* if TRUE the navigation_history isn't
modified if the current folder
changes (used when the back/forward
buttons are pushed) */
static void update_location(JWidget window);
static void update_navigation_buttons(JWidget window);
static void add_in_navigation_history(FileItem *folder);
static void select_filetype_from_filename(JWidget window);
static void goback_command(JWidget widget);
static void goforward_command(JWidget widget);
static void goup_command(JWidget widget);
2007-09-19 07:57:02 +08:00
static bool fileview_msg_proc(JWidget widget, JMessage msg);
static bool location_msg_proc(JWidget widget, JMessage msg);
static bool filetype_msg_proc(JWidget widget, JMessage msg);
2007-09-19 07:57:02 +08:00
/**
* Shows the dialog to select a file in ASE.
*
* Mainly it uses:
* - the 'core/file_system' routines.
* - the 'widgets/fileview' widget.
2007-09-19 07:57:02 +08:00
*/
jstring ase_file_selector(const jstring& message,
const jstring& init_path,
const jstring& exts)
2007-09-19 07:57:02 +08:00
{
static JWidget window = NULL;
FileItem *start_folder = NULL;
JWidget fileview, box, ok;
JWidget goback, goforward, goup;
JWidget filename_entry;
JWidget filetype;
jstring result;
file_system_refresh();
if (!navigation_history) {
navigation_history = jlist_new();
2008-10-01 05:01:54 +08:00
app_add_hook(APP_EXIT,
reinterpret_cast<void(*)(void*)>(jlist_free),
navigation_history);
}
// use the current path
jstring start_folder_path;
2007-09-19 07:57:02 +08:00
// if init_path doesn't contain a path...
if (init_path.filepath().empty()) {
// get the saved `path' in the configuration file
jstring path = get_config_string("FileSelect", "CurrentDirectory", "");
start_folder = get_fileitem_from_path(path.c_str());
2007-09-19 07:57:02 +08:00
// is the folder find?
if (!start_folder) {
// if the `path' doesn't exist...
if (path.empty() || (!ji_dir_exists(path.c_str()))) {
// we can get the current `path' from the system
2007-09-19 07:57:02 +08:00
#ifdef HAVE_DRIVES
int drive = _al_getdrive();
2007-09-19 07:57:02 +08:00
#else
int drive = 0;
2007-09-19 07:57:02 +08:00
#endif
char tmp[1024];
_al_getdcwd(drive, tmp, sizeof(tmp) - ucwidth(OTHER_PATH_SEPARATOR));
path = tmp;
}
2007-09-19 07:57:02 +08:00
start_folder_path = path / init_path;
}
2007-09-19 07:57:02 +08:00
}
else {
// remove the filename
start_folder_path = init_path.filepath() / "";
}
start_folder_path.fix_separators();
if (!start_folder)
start_folder = get_fileitem_from_path(start_folder_path.c_str());
if (!window) {
JWidget view, location;
2007-09-19 07:57:02 +08:00
/* load the window widget */
window = load_widget("filesel.jid", "file_selector");
if (!window)
return NULL;
2007-09-19 07:57:02 +08:00
box = jwidget_find_name(window, "box");
goback = jwidget_find_name(window, "goback");
goforward = jwidget_find_name(window, "goforward");
goup = jwidget_find_name(window, "goup");
location = jwidget_find_name(window, "location");
filetype = jwidget_find_name(window, "filetype");
2007-09-19 07:57:02 +08:00
jwidget_focusrest(goback, FALSE);
jwidget_focusrest(goforward, FALSE);
jwidget_focusrest(goup, FALSE);
2007-09-19 07:57:02 +08:00
add_gfxicon_to_button(goback, GFX_ARROW_LEFT, JI_CENTER | JI_MIDDLE);
add_gfxicon_to_button(goforward, GFX_ARROW_RIGHT, JI_CENTER | JI_MIDDLE);
add_gfxicon_to_button(goup, GFX_ARROW_UP, JI_CENTER | JI_MIDDLE);
2007-09-19 07:57:02 +08:00
jbutton_add_command(goback, goback_command);
jbutton_add_command(goforward, goforward_command);
jbutton_add_command(goup, goup_command);
2007-09-19 07:57:02 +08:00
view = jview_new();
fileview = fileview_new(start_folder, exts.c_str());
2007-09-19 07:57:02 +08:00
jwidget_add_hook(fileview, -1, fileview_msg_proc, NULL);
jwidget_add_hook(location, -1, location_msg_proc, NULL);
jwidget_add_hook(filetype, -1, filetype_msg_proc, NULL);
2007-09-19 07:57:02 +08:00
jwidget_set_name(fileview, "fileview");
jwidget_magnetic(fileview, TRUE);
2007-09-19 07:57:02 +08:00
jview_attach(view, fileview);
jwidget_expansive(view, TRUE);
2007-09-19 07:57:02 +08:00
jwidget_add_child(box, view);
2007-09-19 07:57:02 +08:00
jwidget_set_min_size(window, JI_SCREEN_W*9/10, JI_SCREEN_H*9/10);
jwindow_remap(window);
jwindow_center(window);
}
else {
fileview = jwidget_find_name(window, "fileview");
filetype = jwidget_find_name(window, "filetype");
2007-09-19 07:57:02 +08:00
jwidget_signal_off(fileview);
fileview_set_current_folder(fileview, start_folder);
jwidget_signal_on(fileview);
}
2007-09-19 07:57:02 +08:00
/* current location */
navigation_position = NULL;
add_in_navigation_history(fileview_get_current_folder(fileview));
/* fill the location combo-box */
update_location(window);
update_navigation_buttons(window);
/* fill file-type combo-box */
jcombobox_clear(filetype);
std::vector<jstring> tokens;
std::vector<jstring>::iterator tok;
exts.split(',', tokens);
for (tok=tokens.begin(); tok!=tokens.end(); ++tok)
jcombobox_add_string(filetype, tok->c_str(), NULL);
2007-09-19 07:57:02 +08:00
/* file name entry field */
filename_entry = jwidget_find_name(window, "filename");
jwidget_set_text(filename_entry, init_path.filename().c_str());
select_filetype_from_filename(window);
2007-09-19 07:57:02 +08:00
/* setup the title of the window */
jwidget_set_text(window, message.c_str());
2007-09-19 07:57:02 +08:00
/* get the ok-button */
ok = jwidget_find_name(window, "ok");
2007-09-19 07:57:02 +08:00
/* update the view */
jview_update(jwidget_get_view(fileview));
2007-09-19 07:57:02 +08:00
/* open the window and run... the user press ok? */
jwindow_open_fg(window);
if (jwindow_get_killer(window) == ok ||
jwindow_get_killer(window) == fileview) {
/* open the selected file */
FileItem *folder = fileview_get_current_folder(fileview);
assert(folder != NULL);
2007-09-19 07:57:02 +08:00
jstring buf = fileitem_get_filename(folder);
buf /= jwidget_get_text(filename_entry);
/* does it not have extension? ...we should add the extension
selected in the filetype combo-box */
if (buf.extension().empty()) {
buf += '.';
buf += jcombobox_get_selected_string(filetype);
}
2007-09-19 07:57:02 +08:00
/* duplicate the buffer to return a new string */
result = buf;
/* save the path in the configuration file */
set_config_string("FileSelect", "CurrentDirectory",
fileitem_get_keyname(folder));
2007-09-19 07:57:02 +08:00
}
/* TODO why this doesn't work if I remove this? */
fileview_stop_threads(fileview);
jwidget_free(window);
window = NULL;
return result;
2007-09-19 07:57:02 +08:00
}
/**
* Updates the content of the combo-box that shows the current
* location in the file-system.
2007-09-19 07:57:02 +08:00
*/
static void update_location(JWidget window)
2007-09-19 07:57:02 +08:00
{
char buf[MAX_PATH*2];
JWidget fileview = jwidget_find_name(window, "fileview");
JWidget location = jwidget_find_name(window, "location");
FileItem *current_folder = fileview_get_current_folder(fileview);
FileItem *fileitem = current_folder;
JList locations = jlist_new();
int c, level = 0;
JLink link;
int selected_index = -1;
while (fileitem != NULL) {
jlist_prepend(locations, fileitem);
fileitem = fileitem_get_parent(fileitem);
}
/* clear all the items from the combo-box */
jcombobox_clear(location);
2007-09-19 07:57:02 +08:00
/* add item by item (from root to the specific current folder) */
level = 0;
JI_LIST_FOR_EACH(locations, link) {
2008-10-01 05:01:54 +08:00
fileitem = reinterpret_cast<FileItem*>(link->data);
2007-09-19 07:57:02 +08:00
/* indentation */
ustrcpy(buf, empty_string);
for (c=0; c<level; ++c)
ustrcat(buf, " ");
2007-09-19 07:57:02 +08:00
/* location name */
ustrcat(buf, fileitem_get_displayname(fileitem));
2007-09-19 07:57:02 +08:00
/* add the new location to the combo-box */
jcombobox_add_string(location, buf, fileitem);
2007-09-19 07:57:02 +08:00
if (fileitem == current_folder)
selected_index = level;
level++;
2007-09-19 07:57:02 +08:00
}
jwidget_signal_off(location);
jcombobox_select_index(location, selected_index);
jwidget_set_text(jcombobox_get_entry_widget(location),
fileitem_get_displayname(current_folder));
jentry_deselect_text(jcombobox_get_entry_widget(location));
jwidget_signal_on(location);
2007-09-19 07:57:02 +08:00
jlist_free(locations);
2007-09-19 07:57:02 +08:00
}
static void update_navigation_buttons(JWidget window)
2007-09-19 07:57:02 +08:00
{
JWidget fileview = jwidget_find_name(window, "fileview");
JWidget goback = jwidget_find_name(window, "goback");
JWidget goforward = jwidget_find_name(window, "goforward");
JWidget goup = jwidget_find_name(window, "goup");
FileItem *current_folder = fileview_get_current_folder(fileview);
/* update the state of the go back button: if the navigation-history
has two elements and the navigation-position isn't the first
one */
if (jlist_length(navigation_history) > 1 &&
(!navigation_position ||
navigation_position != jlist_first(navigation_history))) {
jwidget_enable(goback);
}
else {
jwidget_disable(goback);
2007-09-19 07:57:02 +08:00
}
/* update the state of the go forward button: if the
navigation-history has two elements and the navigation-position
isn't the last one */
if (jlist_length(navigation_history) > 1 &&
(!navigation_position ||
navigation_position != jlist_last(navigation_history))) {
jwidget_enable(goforward);
}
else {
jwidget_disable(goforward);
2007-09-19 07:57:02 +08:00
}
/* update the state of the go up button: if the current-folder isn't
the root-item */
if (current_folder != get_root_fileitem())
jwidget_enable(goup);
else
jwidget_disable(goup);
}
2007-09-19 07:57:02 +08:00
static void add_in_navigation_history(FileItem *folder)
{
assert(fileitem_is_folder(folder));
/* remove the history from the current position */
if (navigation_position) {
JLink next;
for (navigation_position = navigation_position->next;
navigation_position != navigation_history->end;
navigation_position = next) {
next = navigation_position->next;
jlist_delete_link(navigation_history,
navigation_position);
}
navigation_position = NULL;
2007-09-19 07:57:02 +08:00
}
/* if the history is empty or if the last item isn't the folder that
we are visiting... */
if (jlist_empty(navigation_history) ||
jlist_last_data(navigation_history) != folder) {
/* ...we can add the location in the history */
jlist_append(navigation_history, folder);
navigation_position = jlist_last(navigation_history);
}
}
2007-09-19 07:57:02 +08:00
static void select_filetype_from_filename(JWidget window)
{
JWidget entry = jwidget_find_name(window, "filename");
JWidget filetype = jwidget_find_name(window, "filetype");
const char *filename = jwidget_get_text(entry);
char *p = get_extension(filename);
char buf[MAX_PATH];
if (p && *p != 0) {
ustrcpy(buf, get_extension(filename));
ustrlwr(buf);
jcombobox_select_string(filetype, buf);
2007-09-19 07:57:02 +08:00
}
}
static void goback_command(JWidget widget)
2007-09-19 07:57:02 +08:00
{
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
2007-09-19 07:57:02 +08:00
if (jlist_length(navigation_history) > 1) {
if (!navigation_position)
navigation_position = jlist_last(navigation_history);
if (navigation_position->prev != navigation_history->end) {
navigation_position = navigation_position->prev;
navigation_locked = TRUE;
fileview_set_current_folder(fileview,
2008-10-01 05:01:54 +08:00
reinterpret_cast<FileItem*>(navigation_position->data));
navigation_locked = FALSE;
2007-09-19 07:57:02 +08:00
}
}
}
static void goforward_command(JWidget widget)
2007-09-19 07:57:02 +08:00
{
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
if (jlist_length(navigation_history) > 1) {
if (!navigation_position)
navigation_position = jlist_first(navigation_history);
2007-09-19 07:57:02 +08:00
if (navigation_position->next != navigation_history->end) {
navigation_position = navigation_position->next;
navigation_locked = TRUE;
fileview_set_current_folder(fileview,
2008-10-01 05:01:54 +08:00
reinterpret_cast<FileItem*>(navigation_position->data));
navigation_locked = FALSE;
2007-09-19 07:57:02 +08:00
}
}
}
static void goup_command(JWidget widget)
2007-09-19 07:57:02 +08:00
{
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
fileview_goup(fileview);
}
2007-09-19 07:57:02 +08:00
/* hook for the 'fileview' widget in the dialog */
static bool fileview_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
case SIGNAL_FILEVIEW_FILE_SELECTED: {
FileItem *fileitem = fileview_get_selected(widget);
if (!fileitem_is_folder(fileitem)) {
JWidget window = jwidget_get_window(widget);
JWidget entry = jwidget_find_name(window, "filename");
const char *filename = fileitem_get_filename(fileitem);
jwidget_set_text(entry, get_filename(filename));
select_filetype_from_filename(window);
}
break;
}
2007-09-19 07:57:02 +08:00
/* when a file is accepted */
case SIGNAL_FILEVIEW_FILE_ACCEPT:
jwidget_close_window(widget);
break;
2007-09-19 07:57:02 +08:00
/* when the current folder change */
case SIGNAL_FILEVIEW_CURRENT_FOLDER_CHANGED: {
JWidget window = jwidget_get_window(widget);
2007-09-19 07:57:02 +08:00
if (!navigation_locked)
add_in_navigation_history(fileview_get_current_folder(widget));
2007-09-19 07:57:02 +08:00
update_location(window);
update_navigation_buttons(window);
break;
}
2007-09-19 07:57:02 +08:00
}
}
return FALSE;
}
2007-09-19 07:57:02 +08:00
/* hook for the 'location' combo-box */
static bool location_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
/* when the user change the location we have to set the
current-folder in the 'fileview' widget */
case JI_SIGNAL_COMBOBOX_SELECT: {
2008-10-01 05:01:54 +08:00
FileItem* fileitem = reinterpret_cast<FileItem*>
(jcombobox_get_data(widget,
jcombobox_get_selected_index(widget)));
if (fileitem) {
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
fileview_set_current_folder(fileview, fileitem);
/* refocus the 'fileview' (the focus in that widget is more
useful for the user) */
jmanager_set_focus(fileview);
}
break;
}
}
}
return FALSE;
}
2007-09-19 07:57:02 +08:00
/* hook for the 'filetype' combo-box */
static bool filetype_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
/* when the user select a new file-type (extension), we have to
change the file-extension in the 'filename' entry widget */
case JI_SIGNAL_COMBOBOX_SELECT: {
const char *ext = jcombobox_get_selected_string(widget);
JWidget window = jwidget_get_window(widget);
JWidget entry = jwidget_find_name(window, "filename");
char buf[MAX_PATH];
char *p;
ustrcpy(buf, jwidget_get_text(entry));
p = get_extension(buf);
if (p && *p != 0) {
ustrcpy(p, ext);
jwidget_set_text(entry, buf);
}
break;
}
2007-09-19 07:57:02 +08:00
}
2007-09-19 07:57:02 +08:00
}
return FALSE;
2007-09-19 07:57:02 +08:00
}