mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
This is it! Beginning to implement icon view! Very fragile - please use
inside gdb for a while. Drag&drop and file ops currently don't work in icon view. Other fixes: - implement Ctrl+arrow and Ctrl+shift+arrow in location bar, create shortcut (Alt+O) - display file permissions - clean some bugs and code cleanup in efiler.cpp
This commit is contained in:
parent
97092a28de
commit
b4578fc6f3
@ -14,19 +14,32 @@
|
||||
#ifndef EDE_FileView_H
|
||||
#define EDE_FileView_H
|
||||
|
||||
#include <Fl/Fl_Shared_Image.H>
|
||||
#include <Fl/Fl_Input.H>
|
||||
|
||||
|
||||
#define USE_FLU_WRAP_GROUP
|
||||
|
||||
|
||||
#include <FL/filename.H> // for FL_PATH_MAX
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_Input.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/IconTheme.h>
|
||||
#include <edelib/Nls.h>
|
||||
|
||||
#include "EDE_Browser.h"
|
||||
|
||||
// This class provides the generic FileView class and two
|
||||
// derived classes called FileIconView and FileDetailsView.
|
||||
// These classes are interchangeable, so that application
|
||||
// can just declare FileView* and use.
|
||||
// FileView is populated with FileItem's.
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
# include "Flu_Wrap_Group.h"
|
||||
#else
|
||||
# include <edelib/ExpandableGroup.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
struct FileItem {
|
||||
edelib::String name; // just the name
|
||||
@ -45,6 +58,625 @@ typedef void (rename_callback_type)(const char*);
|
||||
typedef void (paste_callback_type)(const char*);
|
||||
|
||||
|
||||
#define ICONW 70
|
||||
#define ICONH 80
|
||||
// Spacing to use between icons
|
||||
#define ICON_SPACING 5
|
||||
|
||||
// How many pixels from selection edge will be ignored
|
||||
// (e.g. if selection laso only touches a widget with <5px, it will not be selected)
|
||||
#define SELECTION_EDGE 5
|
||||
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
class FileIconView_ : public Flu_Wrap_Group {
|
||||
#else
|
||||
class FileIconView_ : public edelib::ExpandableGroup {
|
||||
#endif
|
||||
private:
|
||||
// private vars for handling selection and focus
|
||||
// because group doesn't do it
|
||||
int focused;
|
||||
int* m_selected;
|
||||
|
||||
rename_callback_type* rename_callback_;
|
||||
paste_callback_type* paste_callback_;
|
||||
Fl_Callback* context_callback_;
|
||||
|
||||
int select_x1,select_y1,select_x2,select_y2;
|
||||
|
||||
Fl_Button* find_button(edelib::String realpath) {
|
||||
for (int i=0; i<children(); i++) {
|
||||
Fl_Button* b = (Fl_Button*)child(i);
|
||||
char *tmp = (char*)b->user_data();
|
||||
if (realpath==tmp) return b;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public:
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
FileIconView_(int X, int Y, int W, int H, char*label=0) : Flu_Wrap_Group(X,Y,W,H,label)
|
||||
#else
|
||||
FileIconView_(int X, int Y, int W, int H, char*label=0) : edelib::ExpandableGroup(X,Y,W,H,label)
|
||||
#endif
|
||||
{
|
||||
end();
|
||||
box(FL_DOWN_BOX);
|
||||
color(FL_BACKGROUND2_COLOR);
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
spacing(ICON_SPACING,ICON_SPACING);
|
||||
#endif
|
||||
|
||||
select_x1=select_y1=select_x2=select_y2=0;
|
||||
focused=0;
|
||||
m_selected = 0;
|
||||
|
||||
rename_callback_ = 0;
|
||||
paste_callback_ = 0;
|
||||
context_callback_ = 0;
|
||||
}
|
||||
void insert(int row, FileItem *item) {
|
||||
// update list of selected[] items
|
||||
if (!m_selected)
|
||||
m_selected = (int*)malloc(sizeof(int)*(children()+1));
|
||||
else
|
||||
m_selected = (int*)realloc(m_selected,sizeof(int)*(children()+1));
|
||||
m_selected[children()]=0;
|
||||
|
||||
Fl_Button* b = new Fl_Button(0,0,ICONW,ICONH);
|
||||
b->box(FL_FLAT_BOX);
|
||||
b->color(FL_BACKGROUND2_COLOR);
|
||||
b->align(FL_ALIGN_INSIDE|FL_ALIGN_CENTER|FL_ALIGN_WRAP|FL_ALIGN_CLIP);
|
||||
|
||||
// Set the label
|
||||
char buffer[FL_PATH_MAX];
|
||||
uint j=0;
|
||||
for (uint i=0; i<item->name.length(); i++,j++) {
|
||||
buffer[j] = item->name[i];
|
||||
buffer[j+1] = '\0';
|
||||
if (buffer[j] == '@') { // escape @
|
||||
buffer[++j] = '@';
|
||||
buffer[j+1] = '\0';
|
||||
}
|
||||
b->copy_label(buffer);
|
||||
int lw =0, lh = 0;
|
||||
fl_measure(b->label(), lw, lh);
|
||||
if (lw>ICONW) {
|
||||
if (j==i+2) { // already added 2 newlines
|
||||
buffer[j-2]='.';
|
||||
buffer[j-1]='.';
|
||||
buffer[j]='.';
|
||||
buffer[j+1]='\0';
|
||||
j+=2;
|
||||
break; // for
|
||||
} else { // add newline
|
||||
buffer[j+1]=buffer[j];
|
||||
buffer[j]='\n';
|
||||
buffer[j+2]='\0';
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (j<=item->name.length()+2){
|
||||
buffer[j++]='\n';
|
||||
//buffer[j++]='L';
|
||||
}
|
||||
buffer[j]='\0';
|
||||
b->copy_label(buffer);
|
||||
|
||||
// Tooltip text
|
||||
edelib::String tooltip = _("Name: ")+item->name;
|
||||
if (item->size != "") tooltip += _("\nSize: ")+item->size;
|
||||
tooltip += _("\nType: ")+item->description+_("\nDate: ")+item->date+_("\nPermissions: ")+item->permissions;
|
||||
b->tooltip(strdup(tooltip.c_str()));
|
||||
b->user_data(strdup(item->realpath.c_str()));
|
||||
|
||||
// Set icon
|
||||
edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_MEDIUM);
|
||||
if (icon=="") icon = edelib::IconTheme::get("misc",edelib::ICON_SIZE_MEDIUM,edelib::ICON_CONTEXT_MIMETYPE);
|
||||
b->image(Fl_Shared_Image::get(icon.c_str()));
|
||||
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
Flu_Wrap_Group::insert(*b,row);
|
||||
#else
|
||||
edelib::ExpandableGroup::insert(*b,row);
|
||||
#endif
|
||||
//insert(*b,row); -- why doesn't this work?
|
||||
redraw();
|
||||
}
|
||||
void add(FileItem *item) { insert(children()+1, item); }
|
||||
|
||||
void remove(FileItem *item) {
|
||||
Fl_Button* b = find_button(item->realpath);
|
||||
if (b) {
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
Flu_Wrap_Group::remove(*b); // note that FWG requires to dereference the pointer
|
||||
#else
|
||||
edelib::ExpandableGroup::remove(b);
|
||||
#endif
|
||||
//remove(b);
|
||||
delete b;
|
||||
}
|
||||
}
|
||||
|
||||
void remove(int row) {
|
||||
if (row<1 || row>children()) return;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
Flu_Wrap_Group::remove(*b); // note that FWG requires to dereference the pointer
|
||||
#else
|
||||
edelib::ExpandableGroup::remove(b);
|
||||
#endif
|
||||
//remove(b);
|
||||
delete b;
|
||||
}
|
||||
|
||||
|
||||
void update(FileItem *item) {
|
||||
Fl_Button* b = find_button(item->realpath);
|
||||
if (!b) return;
|
||||
|
||||
// Tooltip text
|
||||
edelib::String tooltip = _("Name: ")+item->name+_("\nSize: ")+item->size+_("\nType: ")+item->description+_("\nDate: ")+item->date+_("\nPermissions: ")+item->permissions;
|
||||
b->tooltip(strdup(tooltip.c_str()));
|
||||
|
||||
// Set icon
|
||||
edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_MEDIUM);
|
||||
if (icon=="") icon = edelib::IconTheme::get("misc",edelib::ICON_SIZE_MEDIUM,edelib::ICON_CONTEXT_MIMETYPE);
|
||||
b->image(Fl_Shared_Image::get(icon.c_str()));
|
||||
|
||||
b->redraw();
|
||||
}
|
||||
|
||||
// This is needed because update() uses path to find item in list
|
||||
void update_path(const char* oldpath,const char* newpath) {
|
||||
Fl_Button* b = find_button(oldpath);
|
||||
if (!b) return;
|
||||
b->user_data(strdup(newpath));
|
||||
}
|
||||
|
||||
// Set item to "disabled"
|
||||
void gray(int row) {
|
||||
if (row<1 || row>children()) return;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
// FIXME this also means that item can't be selected
|
||||
b->deactivate();
|
||||
}
|
||||
// Set item to "enabled"
|
||||
void ungray(int row) {
|
||||
if (row<1 || row>children()) return;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
b->activate();
|
||||
}
|
||||
|
||||
// Setup callback that will be used when renaming and dnd
|
||||
void rename_callback(rename_callback_type* cb) { rename_callback_ = cb; }
|
||||
void paste_callback(paste_callback_type* cb) { paste_callback_ = cb; }
|
||||
void context_callback(Fl_Callback* cb) { context_callback_ = cb; }
|
||||
|
||||
// Item real path (data value)
|
||||
const char* path(int row) {
|
||||
if (row<1 || row>children()) return 0;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
return (const char*)b->user_data();
|
||||
}
|
||||
|
||||
// Is item selected?
|
||||
int selected(int row) {
|
||||
if (row<1 || row>children()) return 0;
|
||||
int i=0;
|
||||
while(m_selected[i]!=0)
|
||||
if (m_selected[i++]==row) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Select item (if value=1) or unselect (if value=0)
|
||||
void select(int row, int value) {
|
||||
if (row<1 || row>children()) return;
|
||||
if (!m_selected) return; // shouldn't happen
|
||||
set_focus(row);
|
||||
int i=0;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
if (value) {
|
||||
while (m_selected[i++]!=0);
|
||||
m_selected[i]=row;
|
||||
|
||||
b->color(FL_SELECTION_COLOR);
|
||||
b->labelcolor(fl_contrast(FL_FOREGROUND_COLOR,FL_SELECTION_COLOR));
|
||||
b->redraw();
|
||||
} else {
|
||||
while (m_selected[i]!=0) {
|
||||
if (m_selected[i]==row) {
|
||||
int j=i;
|
||||
while (m_selected[j]!=0) {
|
||||
m_selected[j]=m_selected[j+1];
|
||||
j++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
b->color(FL_BACKGROUND2_COLOR);
|
||||
b->labelcolor(FL_FOREGROUND_COLOR);
|
||||
b->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
// Return nr. of widget that has keyboard focus
|
||||
int get_focus() {
|
||||
/*#ifdef USE_FLU_WRAP_GROUP
|
||||
fprintf( stderr, "---- get_focus()=%d\n", focused);
|
||||
return focused;
|
||||
#else*/
|
||||
Fl_Widget* focus = Fl::focus();
|
||||
int i = find(focus); // Fl_Group method
|
||||
if (i<children()) return i+1;
|
||||
else return 0;
|
||||
//#endif
|
||||
}
|
||||
|
||||
// Scroll view until item becomes visible
|
||||
void show_item(int row) {
|
||||
fprintf(stderr, "show_item(%d)\n", row);
|
||||
if (row<1 || row>children()) return;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
// scroll_to() will scroll widget to the top of view
|
||||
// I prefer that view is scrolled just enough so icon is visible
|
||||
// FIXME: sometimes b->y() is so large that it wraps around and becomes positive
|
||||
if (b->y()+b->h() > y()+h()) {
|
||||
int scrollto = scrollbar.value() + (b->y()+b->h()-y()-h())+1;
|
||||
fprintf (stderr, "by: %d bh: %d y: %d h: %d sv: %d\n", b->y(), b->h(), y(), h(), scrollbar.value());
|
||||
((Fl_Valuator*)&scrollbar)->value(scrollto);
|
||||
redraw();
|
||||
draw(); // we need to relayout the group so that b->y() value is updated for next call
|
||||
}
|
||||
if (b->y() < y())
|
||||
scroll_to(b);
|
||||
#else
|
||||
// Not tested and probably broken:
|
||||
Fl_Scrollbar* s = get_scroll();
|
||||
if (b->y() > s->value()+h()) {
|
||||
// Widget is below current view
|
||||
scrolly(b->y()+b->h()-h());
|
||||
} else if (b->y() < s->value()) {
|
||||
// Widget is above current view
|
||||
scrolly(b->y());
|
||||
}
|
||||
// else { widget is visible, do nothing }
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set keyboard focus to given item
|
||||
void set_focus(int row) {
|
||||
fprintf( stderr, "---- set_focus(%d)\n", row);
|
||||
if (row<1 || row>children()) return;
|
||||
Fl_Button* b = (Fl_Button*)child(row-1);
|
||||
b->take_focus();
|
||||
show_item(row);
|
||||
focused=row;
|
||||
}
|
||||
|
||||
|
||||
// Overloaded handle() method, see inline comments for details
|
||||
int handle(int e) {
|
||||
//fprintf (stderr, " -- FileIconView - Event %d\n",e);
|
||||
|
||||
// Fixes for focus management
|
||||
// fltk provides focus management for members of Fl_Group, but it has minor problems:
|
||||
// - when pressing Alt+Tab, focused widget is forgotten
|
||||
// - if no widget is focused, arrow keys will navigate outside group
|
||||
// - Tab has same effect as right arrow
|
||||
|
||||
|
||||
if (Fl::focus()->inside(this)) { // is focus inside?
|
||||
int k = Fl::event_key();
|
||||
//fprintf(stderr, "event: %d key: %d\n",e,k);
|
||||
if (k==FL_Up || k==FL_Down || k==FL_Left || k==FL_Right) {
|
||||
// Wrap around
|
||||
// FL_KEYDOWN happens only if key is otherwise unhandled
|
||||
if (e==FL_KEYDOWN) {
|
||||
int x = get_focus()-1;
|
||||
Fl_Widget* b = child(x);
|
||||
Fl_Widget* b2;
|
||||
if (k==FL_Up) b2=above(b);
|
||||
if (k==FL_Down) b2=below(b);
|
||||
// Bug in Flu_Wrap_Group - inconsistent behavior of below()
|
||||
if (k==FL_Down && b2==b) b2=child(children()-1);
|
||||
if (k==FL_Left) b2=left(b);
|
||||
if (k==FL_Right) b2=next(b);
|
||||
if (((k==FL_Up) || (k==FL_Left)) && x==0)
|
||||
b2=child(children()-1);
|
||||
if (((k==FL_Down) || (k==FL_Right)) && x==children()-1)
|
||||
b2=child(0);
|
||||
for (int i=0; i<children(); i++)
|
||||
if (b2==child(i)) set_focus(i+1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Remember focus for restoring later
|
||||
if (e==FL_KEYUP || e==FL_KEYBOARD) {// Sometimes only one of these is triggered
|
||||
focused = get_focus();
|
||||
if (!focused) {
|
||||
// Nothing is focused
|
||||
if (k==FL_Up || k==FL_Left)
|
||||
set_focus(children());
|
||||
else
|
||||
set_focus(1);
|
||||
} else
|
||||
show_item(focused); // scroll follows focus
|
||||
return 1; // Don't let fltk navigate to another widget
|
||||
}
|
||||
}
|
||||
|
||||
// Tab key should always navigate outside group
|
||||
if (e!=FL_NO_EVENT && e!=FL_KEYUP && k==FL_Tab) { // NO_EVENT happens before widget gets focus
|
||||
fprintf(stderr, "TAB %d - focused: (%s)\n",e,Fl::focus()->label());
|
||||
// Because widgets can be *very* nested, we go straight
|
||||
// to window()
|
||||
Fl_Group* master=window();
|
||||
Fl_Widget* jumpto=0;
|
||||
int i=0;
|
||||
while (jumpto==0 && master!=this) {
|
||||
jumpto=master->child(i);
|
||||
fprintf (stderr, " -- (%s)\n", jumpto->label());
|
||||
if (this->inside(jumpto) || !jumpto->visible())
|
||||
jumpto=0;
|
||||
i++;
|
||||
if (i==master->children()) {
|
||||
int j;
|
||||
for (j=0; j<master->children(); j++)
|
||||
if (master->child(j)->visible()) break;
|
||||
if (j==master->children()) {// nothing is visible!?
|
||||
master=(Fl_Group*)this;
|
||||
fprintf (stderr, "WTF\n");
|
||||
}else{
|
||||
master=(Fl_Group*)master->child(j);
|
||||
fprintf (stderr, " -> [%s]\n", master->label());
|
||||
}
|
||||
i=0;
|
||||
}
|
||||
if (jumpto!=0 && !jumpto->take_focus())
|
||||
jumpto=0; // widget refused focus, keep searching
|
||||
}
|
||||
fprintf (stderr, "[X]\n");
|
||||
// if this is the only widget, do nothing
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (e==FL_FOCUS) {
|
||||
// Restore focused widget after losing focus
|
||||
if (focused) set_focus(focused);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*#ifdef USE_FLU_WRAP_GROUP
|
||||
int k = Fl::event_key();
|
||||
// if (e==FL_KEYBOARD) fprintf (stderr, "Key: %d", k);
|
||||
if ((e==FL_KEYUP || e==FL_KEYBOARD) && (k==FL_Up || k==FL_Down || k==FL_Left || k==FL_Right)) {
|
||||
Fl_Widget* nextw=0;
|
||||
if (focused) {
|
||||
Fl_Widget* currentw = child(focused-1);
|
||||
switch(k) { // Flu_Wrap_Group methods:
|
||||
case FL_Up:
|
||||
nextw = above(currentw); break;
|
||||
case FL_Down:
|
||||
nextw = below(currentw); break;
|
||||
case FL_Left:
|
||||
nextw = left(currentw); break;
|
||||
case FL_Right:
|
||||
nextw = next(currentw); break;
|
||||
}
|
||||
// Flu_Wrap_Group bug: all methods will wrap around EXCEPT
|
||||
// Flu_Wrap_Group::below() ?!
|
||||
if (k==FL_Down && nextw==currentw)
|
||||
nextw = child(0);
|
||||
}
|
||||
fprintf (stderr, "Event k: %d focused: %d\n", k, focused);
|
||||
|
||||
if (focused && nextw)
|
||||
for (int i=0; i<children(); i++) {
|
||||
if (child(i) == nextw) {
|
||||
fprintf (stderr, "Call %d\n", i);
|
||||
set_focus(i+1);
|
||||
}
|
||||
}
|
||||
else // No widget is selected, or it is first/last
|
||||
switch(k) {
|
||||
// TODO: wrap around
|
||||
case FL_Up:
|
||||
case FL_Left:
|
||||
set_focus(children()); break;
|
||||
case FL_Down:
|
||||
case FL_Right:
|
||||
set_focus(1); break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (e==FL_FOCUS) {
|
||||
// Restore focused widget after losing focus
|
||||
if (focused) set_focus(focused);
|
||||
return 1;
|
||||
}
|
||||
#endif*/
|
||||
|
||||
// We accept mouse clicks
|
||||
if (e==FL_PUSH && Fl::event_x()>x() && Fl::event_x() < x()+w()-Fl::scrollbar_size()) {
|
||||
return 1;
|
||||
}
|
||||
// We accept focus (defaults to 0 with FL_GROUP)
|
||||
if (e==FL_FOCUS) return 1;
|
||||
|
||||
// Do callback on enter key
|
||||
// (because icons don't have callbacks)
|
||||
if (e==FL_KEYBOARD && Fl::event_key()==FL_Enter) {
|
||||
do_callback();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Drag to select (a.k.a. "laso") operation
|
||||
// Draw a dashed line around icons
|
||||
static bool laso=false;
|
||||
if (e==FL_DRAG) {
|
||||
fprintf (stderr, "FL_DRAG! ");
|
||||
if (!laso) {
|
||||
fprintf (stderr, "- begin.\n");
|
||||
laso=true;
|
||||
// Set coordinates for selection box (drawn in draw())
|
||||
select_x1=select_x2=Fl::event_x();
|
||||
select_y1=select_y2=Fl::event_y();
|
||||
} else {
|
||||
fprintf (stderr, "- box (%d,%d,%d,%d).\n",select_x1,select_y1,select_x2,select_y2);
|
||||
select_x2=Fl::event_x();
|
||||
select_y2=Fl::event_y();
|
||||
redraw();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Mouse button released
|
||||
if (e==FL_RELEASE) {
|
||||
fprintf (stderr, "FL_RELEASE! ");
|
||||
// Unselect everything unless Shift or Ctrl is held
|
||||
if (!Fl::event_state(FL_SHIFT) && !Fl::event_state(FL_CTRL)) {
|
||||
for (int i=0;i<children();i++) {
|
||||
// We cannot use select(i+1,0) because that would mess with focus
|
||||
Fl_Button* b = (Fl_Button*)child(i);
|
||||
b->color(FL_BACKGROUND2_COLOR);
|
||||
b->labelcolor(FL_FOREGROUND_COLOR);
|
||||
}
|
||||
redraw();
|
||||
int i=0;
|
||||
while (m_selected[i]!=0) m_selected[i++]=0;
|
||||
}
|
||||
|
||||
// Stop laso operation
|
||||
if (laso) {
|
||||
fprintf (stderr, "- stop drag.\n");
|
||||
laso=false;
|
||||
|
||||
// Order coordinates
|
||||
int tmp;
|
||||
if (select_x1>select_x2) { tmp=select_x1; select_x1=select_x2; select_x2=tmp; }
|
||||
if (select_y1>select_y2) { tmp=select_y1; select_y1=select_y2; select_y2=tmp; }
|
||||
|
||||
// Don't include the edges
|
||||
select_x1 += SELECTION_EDGE;
|
||||
select_y1 += SELECTION_EDGE;
|
||||
select_x2 -= SELECTION_EDGE;
|
||||
select_y2 -= SELECTION_EDGE;
|
||||
fprintf(stderr, "After fixing the box coords: (%d,%d,%d,%d)\n", select_x1, select_y1, select_x2, select_y2);
|
||||
|
||||
// Calculate which buttons were lasoed
|
||||
int i;
|
||||
for (i=0; i<children(); i++) {
|
||||
Fl_Widget* w = child(i); // shortcuts
|
||||
int wx2 = w->x()+w->w();
|
||||
int wy2 = w->y()+w->h();
|
||||
if (select_x2>w->x() && select_x1<wx2 && select_y2>w->y() && select_y1<wy2) {
|
||||
select(i+1,1);
|
||||
fprintf (stderr, "Select widget: '%20s' (%d,%d,%d,%d)\n", w->label(), w->x(), w->y(), wx2, wy2);
|
||||
}
|
||||
}
|
||||
// TODO: add code for Shift key
|
||||
|
||||
select_x1=select_x2=select_y1=select_y2=0;
|
||||
redraw();
|
||||
|
||||
// Single click
|
||||
} else {
|
||||
// Find child that was clicked
|
||||
int i;
|
||||
for (i=0; i<children(); i++)
|
||||
if (Fl::event_inside(child(i))) {
|
||||
fprintf (stderr, "in child %d\n",i);
|
||||
select(i+1,1);
|
||||
}
|
||||
// TODO: add code for Shift key
|
||||
|
||||
// Didn't click on icon
|
||||
if (i==children()) {
|
||||
this->take_focus(); // Remove focus from all buttons
|
||||
focused=0;
|
||||
}
|
||||
}
|
||||
|
||||
// Right button - call context menu
|
||||
if (Fl::event_button() == 3) {
|
||||
Fl::event_is_click(0); // prevent doubleclicking with right button
|
||||
if (context_callback_) context_callback_(this, (void*)path(get_focus()));
|
||||
}
|
||||
|
||||
// Double-click operation
|
||||
if (Fl::event_clicks()) {
|
||||
do_callback();
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Check if it is drag
|
||||
static bool clicked=false;
|
||||
if (e==FL_PUSH) {
|
||||
fprintf (stderr, "FL_PUSH %d %d...\n",Fl::event_is_click(),Fl::event_clicks());
|
||||
clicked=true;
|
||||
return 1;
|
||||
} else if (e != FL_DRAG && e != FL_NO_EVENT && clicked) {
|
||||
fprintf (stderr, "-- triggered click %d\n",e);
|
||||
clicked=false;
|
||||
// Unselect everything unless Shift or Alt is held
|
||||
if (!Fl::event_key(FL_Shift_L) && !Fl::event_key(FL_Shift_R) && !Fl::event_key(FL_Shift_L))
|
||||
for (int i=0; i<children(); i++)
|
||||
select(i+1,0);
|
||||
|
||||
for (int i=0; i<children(); i++)
|
||||
if (Fl::event_inside(child(i))) {
|
||||
fprintf (stderr, "in child %d\n",i);
|
||||
select(i+1,1);
|
||||
return 0;
|
||||
}
|
||||
fprintf (stderr, "in no child\n");
|
||||
// Didn't click on icon
|
||||
take_focus(); // Remove focus from all buttons
|
||||
}*/
|
||||
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
return Flu_Wrap_Group::handle(e);
|
||||
#else
|
||||
return edelib::ExpandableGroup::handle(e);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// Override draw() for selection box
|
||||
void draw() {
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
Flu_Wrap_Group::draw();
|
||||
#else
|
||||
edelib::ExpandableGroup::draw();
|
||||
#endif
|
||||
if (select_x1>0 && select_y1>0) {
|
||||
fl_color(33);
|
||||
fl_line_style(FL_DASH);
|
||||
fl_line(select_x1,select_y1,select_x1,select_y2);
|
||||
fl_line(select_x1,select_y2,select_x2,select_y2);
|
||||
fl_line(select_x2,select_y2,select_x2,select_y1);
|
||||
fl_line(select_x2,select_y1,select_x1,select_y1);
|
||||
fl_line_style(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Override clear so that we can empty selected & focused values
|
||||
void clear() {
|
||||
focused=0;
|
||||
if (m_selected) free(m_selected);
|
||||
m_selected = 0;
|
||||
#ifdef USE_FLU_WRAP_GROUP
|
||||
Flu_Wrap_Group::clear();
|
||||
#else
|
||||
edelib::ExpandableGroup::clear();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FileDetailsView_ : public EDE_Browser {
|
||||
@ -306,10 +938,14 @@ fprintf (stderr, "value: %s\n", value.c_str());
|
||||
bucket.add(ntext);
|
||||
|
||||
// doesn't work
|
||||
//Fl_Image* im = get_icon(row);
|
||||
Fl_Image* im = get_icon(row)->copy();
|
||||
//im->refresh();
|
||||
//im->uncache(); // doesn't work
|
||||
//im->color_average(FL_BACKGROUND_COLOR, 1.0);
|
||||
//im->data(im->data(),im->count());
|
||||
set_icon(row,im);
|
||||
|
||||
//redraw(); // OPTIMIZE
|
||||
redraw(); // OPTIMIZE
|
||||
}
|
||||
|
||||
|
||||
@ -484,12 +1120,14 @@ fprintf(stderr, "Call FileView::clear()\n");
|
||||
bucket.empty();
|
||||
EDE_Browser::clear();
|
||||
}
|
||||
|
||||
int visible() { return Fl_Widget::visible(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class FileView : public Fl_Group {
|
||||
/*class FileView : public Fl_Group {
|
||||
public:
|
||||
FileView(int X, int Y, int W, int H, char*label=0) : Fl_Group(X,Y,W,H,label) {}
|
||||
|
||||
@ -548,9 +1186,87 @@ public:
|
||||
const char* text(int i) { return browser->text(i); }
|
||||
void text(int i, const char* c) { return browser->text(i,c); }
|
||||
uchar column_char() { return browser->column_char(); }
|
||||
};*/
|
||||
|
||||
enum FileViewType {
|
||||
FILE_DETAILS_VIEW,
|
||||
FILE_ICON_VIEW
|
||||
};
|
||||
|
||||
|
||||
class FileDetailsView : public Fl_Group {
|
||||
private:
|
||||
FileDetailsView_* browser;
|
||||
FileIconView_* icons;
|
||||
FileViewType m_type;
|
||||
public:
|
||||
FileDetailsView(int X, int Y, int W, int H, char*label=0) : Fl_Group(X,Y,W,H,label) {
|
||||
browser = new FileDetailsView_(X,Y,W,H,label);
|
||||
browser->end();
|
||||
// browser->hide();
|
||||
icons = new FileIconView_(X,Y,W,H,label);
|
||||
icons->end();
|
||||
end();
|
||||
|
||||
// Set default to FILE_DETAILS_VIEW
|
||||
icons->hide();
|
||||
m_type=FILE_DETAILS_VIEW;
|
||||
}
|
||||
|
||||
void setType(FileViewType t) {
|
||||
m_type=t;
|
||||
if (t==FILE_DETAILS_VIEW) {
|
||||
icons->hide();
|
||||
//browser->show();
|
||||
}
|
||||
if (t==FILE_ICON_VIEW) {
|
||||
//browser->hide();
|
||||
icons->show();
|
||||
//redraw();
|
||||
}
|
||||
}
|
||||
FileViewType getType() {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
// View methods
|
||||
void insert(int row, FileItem *item) { browser->insert(row,item); icons->insert(row,item); }
|
||||
void add(FileItem *item) { browser->add(item); icons->add(item); }
|
||||
void remove(FileItem *item) { browser->remove(item); icons->remove(item); }
|
||||
void update(FileItem *item) { browser->update(item); icons->update(item); }
|
||||
|
||||
void update_path(const char* oldpath,const char* newpath) { browser->update_path(oldpath,newpath); icons->update_path(oldpath,newpath); }
|
||||
|
||||
void gray(int row) { browser->gray(row); icons->gray(row); }
|
||||
void ungray(int row) { browser->ungray(row); icons->ungray(row); }
|
||||
|
||||
void rename_callback(rename_callback_type* cb) { browser->rename_callback(cb); icons->rename_callback(cb); }
|
||||
void paste_callback(paste_callback_type* cb) { browser->paste_callback(cb); icons->paste_callback(cb); }
|
||||
void context_callback(Fl_Callback* cb) { browser->context_callback(cb); icons->context_callback(cb); }
|
||||
|
||||
// Browser methods
|
||||
const char* path(int i) { if (m_type==FILE_DETAILS_VIEW) return (const char*)browser->data(i); else return icons->path(i); }
|
||||
int size() { if (m_type==FILE_DETAILS_VIEW) return browser->size(); else return icons->children();}
|
||||
int selected(int i) { if (m_type==FILE_DETAILS_VIEW) return browser->selected(i); else return icons->selected(i); }
|
||||
void select(int i, int k) { browser->select(i,k); browser->middleline(i); icons->select(i,k); icons->show_item(i); }
|
||||
int get_focus() { if (m_type==FILE_DETAILS_VIEW) return browser->get_focus(); else return icons->get_focus(); }
|
||||
void set_focus(int i) { browser->set_focus(i); icons->set_focus(i);}
|
||||
void remove(int i) { browser->remove(i); icons->remove(i);}
|
||||
void clear() { browser->clear(); icons->clear();}
|
||||
void callback(Fl_Callback*cb) { browser->callback(cb); icons->callback(cb);}
|
||||
int take_focus() { if (m_type==FILE_DETAILS_VIEW) return browser->take_focus(); else return icons->take_focus(); }
|
||||
|
||||
// These methods are used by do_rename()
|
||||
const char* text(int i) { return browser->text(i); }
|
||||
void text(int i, const char* c) { return browser->text(i,c); }
|
||||
uchar column_char() { return browser->column_char(); }
|
||||
|
||||
// Overloaded...
|
||||
//int handle(int e) { if
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* $Id */
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include <Fl/Fl_Menu_Bar.H>
|
||||
#include <Fl/Fl_File_Chooser.H> // for fl_dir_chooser, used in "Open location"
|
||||
#include <Fl/filename.H>
|
||||
#include <Fl/fl_ask.H>
|
||||
#include <Fl/Fl_File_Input.H> // location bar
|
||||
|
||||
#include <edelib/Nls.h>
|
||||
@ -41,6 +40,7 @@
|
||||
#include "EDE_DirTree.h" // directory tree
|
||||
#include "Util.h" // ex-edelib
|
||||
#include "ede_ask.h" // replacement for fl_ask
|
||||
//#include "Ask.h"
|
||||
|
||||
#include "fileops.h" // file operations
|
||||
#include "filesystem.h" // filesystem support
|
||||
@ -77,6 +77,62 @@ const int statusbar_width = 400;
|
||||
|
||||
int default_tree_width=150;
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
Some improvements to Fl_File_Input, that should be added
|
||||
upstream:
|
||||
* enable to set shortcut in label (STR 1770 for Fl_Input_)
|
||||
* navigate using Ctrl+arrow (here we jump to dir. sep.)
|
||||
-------------------------------------------------------------------*/
|
||||
|
||||
class My_File_Input : public Fl_File_Input {
|
||||
int shortcut_;
|
||||
public:
|
||||
My_File_Input(int X,int Y,int W,int H,const char *label=0) : Fl_File_Input(X,Y,W,H,label) {
|
||||
set_flag(SHORTCUT_LABEL);
|
||||
shortcut_ = 0;
|
||||
}
|
||||
|
||||
int shortcut() const {return shortcut_;}
|
||||
void shortcut(int s) {shortcut_ = s;}
|
||||
|
||||
int handle(int e) {
|
||||
if (e==FL_SHORTCUT) {
|
||||
if (!(shortcut() ? Fl::test_shortcut(shortcut()) : test_shortcut())) return 0;
|
||||
if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this);
|
||||
return 1;
|
||||
}
|
||||
if (e==FL_KEYDOWN) {
|
||||
if (Fl::event_state(FL_CTRL)) {
|
||||
const char* v = value();
|
||||
if (Fl::event_key()==FL_Left) {
|
||||
for (uint i=position()-2; i>=0; i--)
|
||||
if (v[i]=='/') {
|
||||
if (Fl::event_state(FL_SHIFT))
|
||||
position(i+1,mark());
|
||||
else
|
||||
position(i+1,i+1);
|
||||
break;
|
||||
}
|
||||
return 1; // don't go out
|
||||
}
|
||||
if (Fl::event_key()==FL_Right) {
|
||||
for (uint i=position()+1; i<strlen(v); i++)
|
||||
if (v[i]=='/') {
|
||||
if (Fl::event_state(FL_SHIFT))
|
||||
position(i+1,mark());
|
||||
else
|
||||
position(i+1,i+1);
|
||||
break;
|
||||
}
|
||||
return 1; // don't go out
|
||||
}
|
||||
}
|
||||
}
|
||||
return Fl_File_Input::handle(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
@ -151,6 +207,75 @@ int myversionsort(const void *a, const void *b) {
|
||||
return k;
|
||||
}
|
||||
|
||||
// Return a string describing permissions relative to the current user
|
||||
const char* permission_text(mode_t mode, uid_t uid, gid_t gid) {
|
||||
static uid_t uuid = getuid();
|
||||
static gid_t ugid = getgid();
|
||||
// use geteuid() and getegid()? what's the difference?
|
||||
if (S_ISDIR(mode)) {
|
||||
// Directory
|
||||
if (uid == uuid) {
|
||||
if (!(mode&S_IXUSR))
|
||||
return _("Can't enter directory");
|
||||
if (!(mode&S_IRUSR))
|
||||
return _("Can't list directory");
|
||||
if (!(mode&S_IWUSR))
|
||||
return _("Can't add, delete, rename files"); // shorter description?
|
||||
return _("Full permissions");
|
||||
} else if (gid == ugid) {
|
||||
if (!(mode&S_IXGRP))
|
||||
return _("Can't enter directory");
|
||||
if (!(mode&S_IRGRP))
|
||||
return _("Can't list directory");
|
||||
if (!(mode&S_IWGRP))
|
||||
return _("Can't add, delete, rename files");
|
||||
return _("Full permissions");
|
||||
} else {
|
||||
if (!(mode&S_IXOTH))
|
||||
return _("Can't enter directory");
|
||||
if (!(mode&S_IROTH))
|
||||
return _("Can't list directory");
|
||||
if (!(mode&S_IWOTH))
|
||||
return _("Can't add, delete, rename files");
|
||||
return _("Full permissions");
|
||||
}
|
||||
} else {
|
||||
// Regular file (anything else should have similar permissions)
|
||||
if (uid == uuid) {
|
||||
if ((mode&S_IXUSR) && (mode&S_IRUSR) && (mode&S_IWUSR))
|
||||
return _("Read, write, execute");
|
||||
if ((mode&S_IRUSR) && (mode&S_IWUSR))
|
||||
return _("Read, write");
|
||||
if ((mode&S_IXUSR) && (mode&S_IRUSR))
|
||||
return _("Read only, execute");
|
||||
if ((mode&S_IRUSR))
|
||||
return _("Read only");
|
||||
// ignore weird permissions such as "write only"
|
||||
return _("Not readable");
|
||||
} else if (gid == ugid) {
|
||||
if ((mode&S_IXGRP) && (mode&S_IRGRP) && (mode&S_IWGRP))
|
||||
return _("Read, write, execute");
|
||||
if ((mode&S_IRGRP) && (mode&S_IWGRP))
|
||||
return _("Read, write");
|
||||
if ((mode&S_IXGRP) && (mode&S_IRGRP))
|
||||
return _("Read only, execute");
|
||||
if ((mode&S_IRGRP))
|
||||
return _("Read only");
|
||||
return _("Not readable");
|
||||
} else {
|
||||
if ((mode&S_IXOTH) && (mode&S_IROTH) && (mode&S_IWOTH))
|
||||
return _("Read, write, execute");
|
||||
if ((mode&S_IROTH) && (mode&S_IWOTH))
|
||||
return _("Read, write");
|
||||
if ((mode&S_IXOTH) && (mode&S_IROTH))
|
||||
return _("Read only, execute");
|
||||
if ((mode&S_IROTH))
|
||||
return _("Read only");
|
||||
return _("Not readable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loaddir(const char *path) {
|
||||
if (semaphore) return; // Prevent loaddir to interrupt previous loaddir - that can result in crash
|
||||
semaphore=true;
|
||||
@ -159,21 +284,29 @@ void loaddir(const char *path) {
|
||||
char old_dir[FL_PATH_MAX];
|
||||
strncpy(old_dir,current_dir,strlen(current_dir)); // Restore olddir in case of error
|
||||
|
||||
// Sometimes path is just a pointer to current_dir
|
||||
char* tmpath = strdup(path);
|
||||
|
||||
// Set current_dir
|
||||
// fl_filename_isdir() thinks that / isn't a dir :(
|
||||
if (strcmp(path,"/")==0 || fl_filename_isdir(path)) {
|
||||
if (path[0] == '~') // Expand tilde
|
||||
snprintf(current_dir,PATH_MAX,"%s/%s",getenv("HOME"),path+1);
|
||||
else
|
||||
if (path!=current_dir) strcpy(current_dir,path);
|
||||
} else
|
||||
if (path[0] == '~') {// Expand tilde
|
||||
snprintf(current_dir,PATH_MAX,"%s/%s",getenv("HOME"),tmpath+1);
|
||||
} else if (path[0] != '/') { // Relative path
|
||||
snprintf(current_dir,PATH_MAX,"%s/%s",getenv("PWD"),tmpath);
|
||||
} else {
|
||||
if (path!=current_dir) strncpy(current_dir,tmpath,strlen(tmpath)+1);
|
||||
}
|
||||
} else {
|
||||
strcpy(current_dir,getenv("HOME"));
|
||||
}
|
||||
free(tmpath);
|
||||
|
||||
// Trailing slash should always be there
|
||||
if (current_dir[strlen(current_dir)-1] != '/') strcat(current_dir,"/");
|
||||
|
||||
// Compact dotdot (..)
|
||||
if (char *tmp = strstr(current_dir,"/../")) {
|
||||
while (char *tmp = strstr(current_dir,"/../")) {
|
||||
char *tmp2 = tmp+4;
|
||||
tmp--;
|
||||
while (tmp != current_dir && *tmp != '/') tmp--;
|
||||
@ -182,11 +315,9 @@ void loaddir(const char *path) {
|
||||
*tmp='\0';
|
||||
}
|
||||
|
||||
// variables used later
|
||||
// List all files in directory
|
||||
int size=0;
|
||||
dirent **files;
|
||||
|
||||
// List all files in directory
|
||||
if (ignorecase)
|
||||
size = scandir(current_dir, &files, 0, myversionsort);
|
||||
else
|
||||
@ -194,6 +325,7 @@ void loaddir(const char *path) {
|
||||
|
||||
if (size<1) { // there should always be . and ..
|
||||
ede_alert(_("Permission denied!"));
|
||||
// edelib::fl_alert(_("Permission denied!"));
|
||||
strncpy(current_dir,old_dir,strlen(current_dir));
|
||||
semaphore=false;
|
||||
return;
|
||||
@ -238,7 +370,7 @@ fprintf(stderr, "Size: %d\n", size);
|
||||
item->name = n;
|
||||
item->realpath = fullpath;
|
||||
item->date = nice_time(stat_buffer.st_mtime);
|
||||
item->permissions = ""; // todo
|
||||
item->permissions = permission_text(stat_buffer.st_mode,stat_buffer.st_uid,stat_buffer.st_gid);
|
||||
if (strcmp(n,"..")==0) {
|
||||
item->icon = "undo";
|
||||
item->description = "Go up";
|
||||
@ -320,10 +452,12 @@ fprintf (stderr, "ICON: %s !!!!!\n", icon.c_str());
|
||||
Main menu and other callbacks
|
||||
-------------------------------------------------------------------*/
|
||||
|
||||
// This callback is called by doubleclicking on file list, by main and context menu
|
||||
// This callback is called by doubleclicking on file list, by main menu and context menu
|
||||
void open_cb(Fl_Widget*w, void*data) {
|
||||
fprintf (stderr,"cb\n");
|
||||
|
||||
if (Fl::event_clicks() || Fl::event_key() == FL_Enter || w==main_menu || w==context_menu) {
|
||||
|
||||
fprintf (stderr,"enter\n");
|
||||
//if (Fl::event_clicks()) fprintf(stderr, "clicks\n");
|
||||
//if (Fl::event_key()==FL_Enter) fprintf(stderr, "ekey\n");
|
||||
@ -343,7 +477,7 @@ fprintf (stderr,"enter\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Call opener
|
||||
// Find opener
|
||||
mime_resolver.set(path);
|
||||
char* opener = simpleopener(mime_resolver.type().c_str());
|
||||
|
||||
@ -360,7 +494,7 @@ fprintf (stderr,"enter\n");
|
||||
if (opener) {
|
||||
int k=edelib::run_program(o2,false); fprintf(stderr, "retval: %d\n", k);
|
||||
} else
|
||||
statusbar->copy_label(tsprintf(_("No program to open %s!"), fl_filename_name(view->path(view->get_focus()))));
|
||||
statusbar->copy_label(tsprintf(_("No program to open %s!"), fl_filename_name(path)));
|
||||
|
||||
rlim->rlim_cur = old_rlimit;
|
||||
setrlimit (RLIMIT_CORE, rlim);
|
||||
@ -372,14 +506,12 @@ fprintf (stderr,"enter\n");
|
||||
|
||||
|
||||
// Main menu callbacks
|
||||
void location_cb(Fl_Widget*, void*) {
|
||||
const char *dir = fl_dir_chooser(_("Choose location"),current_dir);
|
||||
if (dir) loaddir(dir);
|
||||
void new_cb(Fl_Widget*, void*) {
|
||||
// FIXME: use program path
|
||||
edelib::run_program(tsprintf("efiler %s",current_dir),false);
|
||||
}
|
||||
|
||||
void new_cb(Fl_Widget*, void*) { edelib::run_program(tsprintf("efiler %s",current_dir),false); }
|
||||
|
||||
void quit_cb(Fl_Widget*, void*) {exit(0);}
|
||||
void quit_cb(Fl_Widget*, void*) { win->hide(); }
|
||||
|
||||
void cut_cb(Fl_Widget*, void*) { do_cut_copy(false); }
|
||||
void copy_cb(Fl_Widget*, void*) { do_cut_copy(true); }
|
||||
@ -391,14 +523,12 @@ void showtree_cb(Fl_Widget*, void*) {
|
||||
showtree = !showtree;
|
||||
if (!showtree) {
|
||||
tree_width = dirtree->w();
|
||||
tile->position(default_tree_width, 1, 1, 1); // NOTE!
|
||||
tile->position(default_tree_width, 1, 1, 1); // NOTE this doesn't always work!
|
||||
fprintf(stderr, "Hide tree: %d\n", tree_width);
|
||||
// showtree->clear();
|
||||
} else {
|
||||
int currentw = dirtree->w();
|
||||
tile->position(currentw, 1, tree_width, 1);
|
||||
fprintf(stderr, "Show tree: %d %d\n", currentw, tree_width);
|
||||
// showtree->set();
|
||||
}
|
||||
}
|
||||
|
||||
@ -412,12 +542,15 @@ void locationbar_cb(Fl_Widget*, void*) {
|
||||
location_bar->show();
|
||||
location_bar->resize(0, menubar_height, win->w(), location_bar_height);
|
||||
tile->resize(0, menubar_height+location_bar_height, win->w(), win->h()-menubar_height-location_bar_height-statusbar_height);
|
||||
// win->resizable(tile); // win keeps old tile size...
|
||||
win->redraw();
|
||||
} else {
|
||||
location_bar->hide();
|
||||
// location_bar->resize(0, menubar_height, win->w(), 0);
|
||||
tile->resize(0, menubar_height, win->w(), win->h()-menubar_height-statusbar_height);
|
||||
win->redraw();
|
||||
win->resizable(tile);
|
||||
win->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,14 +568,25 @@ void case_cb(Fl_Widget*, void*) {
|
||||
loaddir(current_dir);
|
||||
}
|
||||
|
||||
void dirsfirst_cb(Fl_Widget*, void*) { dirsfirst=!dirsfirst; loaddir(current_dir); }
|
||||
void dirsfirst_cb(Fl_Widget*, void*) {
|
||||
dirsfirst=!dirsfirst;
|
||||
loaddir(current_dir);
|
||||
}
|
||||
|
||||
|
||||
// dummy callbacks - TODO
|
||||
void ow_cb(Fl_Widget*, void*) { fprintf(stderr, "callback\n"); } // make a list of openers
|
||||
void pref_cb(Fl_Widget*, void*) { fprintf(stderr, "callback\n"); }
|
||||
void iconsview_cb(Fl_Widget*, void*) { fprintf(stderr, "callback\n"); }
|
||||
void listview_cb(Fl_Widget*, void*) { fprintf(stderr, "callback\n"); }
|
||||
void iconsview_cb(Fl_Widget*, void*) {
|
||||
//fprintf(stderr, "callback\n");
|
||||
view->setType(FILE_ICON_VIEW);
|
||||
loaddir(current_dir);
|
||||
}
|
||||
void listview_cb(Fl_Widget*, void*) {
|
||||
//fprintf(stderr, "callback\n");
|
||||
view->setType(FILE_DETAILS_VIEW);
|
||||
loaddir(current_dir);
|
||||
}
|
||||
void about_cb(Fl_Widget*, void*) { fprintf(stderr, "callback\n"); }
|
||||
void aboutede_cb(Fl_Widget*, void*) { fprintf(stderr, "callback\n"); }
|
||||
|
||||
@ -461,12 +605,12 @@ void tree_cb(Fl_Widget*, void*) {
|
||||
// and callbacks for shortcut buttons
|
||||
// location_input is set to FL_WHEN_CHANGED
|
||||
void location_input_cb(Fl_Widget*, void*) {
|
||||
fprintf (stderr, "location_input_cb %d\n",Fl::event());
|
||||
if (Fl::event_key() == FL_Enter || Fl::event()==FL_RELEASE)
|
||||
if (Fl::event_key() == FL_Enter || Fl::event()==FL_RELEASE)
|
||||
// second event is click on button
|
||||
loaddir(location_input->value());
|
||||
|
||||
if (Fl::event()==FL_KEYDOWN && Fl::event_key()!=FL_BackSpace) {
|
||||
// Pressing a key in Fl_Input will automatically replace selection with that key
|
||||
if (Fl::event()==FL_KEYDOWN && Fl::event_key()!=FL_BackSpace && Fl::event_key()!=FL_Delete) {
|
||||
// Pressing a key in Fl_Input will automatically replace selection with that char
|
||||
// So there are really two possibilities:
|
||||
// 1. Cursor is at the end, we add autocomplete stuff at cursor pos
|
||||
// 2. Cursor is in the middle, we do nothing
|
||||
@ -478,7 +622,6 @@ fprintf (stderr, "location_input_cb %d\n",Fl::event());
|
||||
int mark = location_input->mark();
|
||||
|
||||
// To avoid scandir, we will use view contents
|
||||
// smart, eh? :)
|
||||
if ((strlen(loc)>strlen(current_dir)) && (!strchr(loc+strlen(current_dir),'/'))) {
|
||||
int i;
|
||||
for (i=1; i<=view->size(); i++) {
|
||||
@ -532,6 +675,8 @@ fprintf (stderr, "location_input_cb %d\n",Fl::event());
|
||||
|
||||
|
||||
|
||||
// TODO: move this to view
|
||||
// every item should have own context menu defined
|
||||
|
||||
Fl_Menu_Item context_menu_definition[] = {
|
||||
{_("&Open"), 0, open_cb},
|
||||
@ -546,7 +691,6 @@ Fl_Menu_Item context_menu_definition[] = {
|
||||
|
||||
// Right click - show context menu
|
||||
void context_cb(Fl_Widget*, void*) {
|
||||
// context_menu->position(Fl::event_x_root(),Fl::event_y_root());
|
||||
context_menu->popup();
|
||||
context_menu->value(-1);
|
||||
}
|
||||
@ -580,9 +724,9 @@ Fl_Menu_Item main_menu_definition[] = {
|
||||
{_("&Detailed list"), FL_F+8, listview_cb, 0, FL_MENU_RADIO|FL_MENU_VALUE|FL_MENU_DIVIDER},
|
||||
{_("Directory &tree"), FL_F+9, showtree_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE},
|
||||
{_("&Location bar"), FL_F+10, locationbar_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE},
|
||||
{_("&Show hidden"), 0, showhidden_cb, 0, FL_MENU_TOGGLE|FL_MENU_DIVIDER},
|
||||
{_("&Hidden files"), 0, showhidden_cb, 0, FL_MENU_TOGGLE|FL_MENU_DIVIDER},
|
||||
{_("&Refresh"), FL_F+5, refresh_cb},
|
||||
{_("S&ort"), 0, 0, 0, FL_SUBMENU},
|
||||
{_("&Sort"), 0, 0, 0, FL_SUBMENU},
|
||||
{_("&Case sensitive"), 0, case_cb, 0, FL_MENU_TOGGLE},
|
||||
{_("D&irectories first"), 0, dirsfirst_cb, 0, FL_MENU_TOGGLE|FL_MENU_VALUE},
|
||||
{0},
|
||||
@ -598,7 +742,7 @@ Fl_Menu_Item main_menu_definition[] = {
|
||||
|
||||
|
||||
// Main program
|
||||
|
||||
extern int FL_NORMAL_SIZE;
|
||||
int main (int argc, char **argv) {
|
||||
|
||||
// Parse command line - this must come first
|
||||
@ -608,8 +752,8 @@ int main (int argc, char **argv) {
|
||||
current_dir[0]='\0';
|
||||
else {
|
||||
if (strcmp(argv[unknown],"--help")==0) {
|
||||
printf("EFiler - EDE File Manager\nPart of Equinox Desktop Environment (EDE).\nCopyright (c) 2000-2007 EDE Authors.\n\nThis program is licenced under terms of the\nGNU General Public Licence version 2 or newer.\nSee COPYING for details.\n\n");
|
||||
printf("Usage:\n\tefiler [OPTIONS] [PATH]\n\n");
|
||||
printf(_("EFiler - EDE File Manager\nPart of Equinox Desktop Environment (EDE).\nCopyright (c) 2000-2007 EDE Authors.\n\nThis program is licenced under terms of the\nGNU General Public Licence version 2 or newer.\nSee COPYING for details.\n\n"));
|
||||
printf(_("Usage:\n\tefiler [OPTIONS] [PATH]\n\n"));
|
||||
printf("%s\n",Fl::help);
|
||||
return 1;
|
||||
}
|
||||
@ -624,6 +768,8 @@ FL_NORMAL_SIZE=12;
|
||||
fl_message_font(FL_HELVETICA, 12);
|
||||
|
||||
|
||||
// Main GUI design
|
||||
|
||||
win = new Fl_Double_Window(default_window_width, default_window_height);
|
||||
// win->color(FL_WHITE);
|
||||
win->begin();
|
||||
@ -632,12 +778,12 @@ fl_message_font(FL_HELVETICA, 12);
|
||||
|
||||
location_bar = new Fl_Group(0, menubar_height, default_window_width, location_bar_height);
|
||||
location_bar->begin();
|
||||
location_input = new Fl_File_Input(70, menubar_height+2, default_window_width-200, location_bar_height-5, _("Location:"));
|
||||
location_input = new My_File_Input(70, menubar_height+2, default_window_width-200, location_bar_height-5, _("L&ocation:"));
|
||||
location_input->align(FL_ALIGN_LEFT);
|
||||
location_input->callback(location_input_cb);
|
||||
location_input->when(FL_WHEN_ENTER_KEY_CHANGED);
|
||||
location_bar->end();
|
||||
location_bar->box(FL_UP_BOX); // hack for label size
|
||||
location_bar->box(FL_UP_BOX);
|
||||
location_bar->resizable(location_input);
|
||||
|
||||
tile = new Fl_Tile(0, menubar_height+location_bar_height, default_window_width, default_window_height-menubar_height-location_bar_height-statusbar_height);
|
||||
@ -647,7 +793,7 @@ fl_message_font(FL_HELVETICA, 12);
|
||||
|
||||
view = new FileDetailsView(150, menubar_height+location_bar_height, default_window_width-default_tree_width, default_window_height-menubar_height-location_bar_height-statusbar_height);
|
||||
view->callback(open_cb);
|
||||
// callback for renaming
|
||||
// callbacks for file ops
|
||||
view->rename_callback(do_rename);
|
||||
view->paste_callback(do_paste);
|
||||
view->context_callback(context_cb);
|
||||
@ -657,7 +803,7 @@ fl_message_font(FL_HELVETICA, 12);
|
||||
statusbar = new Fl_Box(2, default_window_height-statusbar_height+2, statusbar_width, statusbar_height-4);
|
||||
statusbar->box(FL_DOWN_BOX);
|
||||
statusbar->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
|
||||
statusbar->label(_("Ready."));
|
||||
statusbar->label(_("EFiler is starting..."));
|
||||
|
||||
Fl_Box* filler = new Fl_Box(statusbar_width+2, default_window_height-statusbar_height+2, default_window_width-statusbar_width, statusbar_height-4);
|
||||
sbgroup->end();
|
||||
@ -672,22 +818,22 @@ fl_message_font(FL_HELVETICA, 12);
|
||||
win->resizable(tile);
|
||||
// win->resizable(view);
|
||||
|
||||
// Set application (window manager) icon
|
||||
// FIXME: due to fltk bug this icon doesn't have transparency
|
||||
fl_open_display();
|
||||
Pixmap p, mask;
|
||||
|
||||
XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), efiler_xpm, &p, &mask, NULL);
|
||||
win->icon((char*)p);
|
||||
|
||||
win->show(argc,argv);
|
||||
view->take_focus();
|
||||
|
||||
// Yet another hack for label size....
|
||||
|
||||
// TODO remember previous configuration
|
||||
showhidden=false; dirsfirst=true; ignorecase=true; semaphore=false; showtree=true; showlocation=true;
|
||||
tree_width = default_tree_width;
|
||||
|
||||
win->show(argc,argv);
|
||||
view->take_focus();
|
||||
dirtree->init();
|
||||
loaddir(current_dir);
|
||||
|
||||
return Fl::run();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user