2fbf67cb29
* NEW: Update FSF address in every source file. git-svn-id: svn://localhost/gambas/trunk@3870 867c0c6c-44f3-4631-809d-bfa615b0a4ec
469 lines
9.5 KiB
C++
469 lines
9.5 KiB
C++
/***************************************************************************
|
|
|
|
gtreeview.cpp
|
|
|
|
(c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
|
|
|
|
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, 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA.
|
|
|
|
***************************************************************************/
|
|
|
|
#include "widgets.h"
|
|
#include "widgets_private.h"
|
|
#include "gtree.h"
|
|
#include "gtreeview.h"
|
|
|
|
/**************************************************************************
|
|
|
|
gTreeView
|
|
|
|
***************************************************************************/
|
|
|
|
static void cb_activate(GtkTreeView *widget, GtkTreePath *path, GtkTreeViewColumn *column, gTreeView *control)
|
|
{
|
|
char *key = control->find(path);
|
|
control->setItemExpanded(key, !control->isItemExpanded(key));
|
|
// Be careful, do not reuse key, as it can be destroyed during the Expand event
|
|
control->emit(SIGNAL(control->onActivate), control->find(path));
|
|
}
|
|
|
|
static void cb_select(GtkTreeSelection *selection, gTreeView *control)
|
|
{
|
|
control->emit(SIGNAL(control->onSelect));
|
|
}
|
|
|
|
static void cb_click(GtkWidget *widget, gTreeView *control)
|
|
{
|
|
control->emit(SIGNAL(control->onClick));
|
|
}
|
|
|
|
static bool cb_button_press(GtkWidget *widget, GdkEventButton *e, gTreeView *control)
|
|
{
|
|
if (e->button != 1)
|
|
control->setCurrent(control->find((int)e->x, (int)e->y));
|
|
return false;
|
|
}
|
|
|
|
static void cb_expand(GtkTreeView *widget, GtkTreeIter *iter, GtkTreePath *path, gTreeView *control)
|
|
{
|
|
if (control->locked())
|
|
return;
|
|
|
|
char *key = control->find(path);
|
|
control->refreshExpanded(key, true);
|
|
control->emit(SIGNAL(control->onExpand), key);
|
|
}
|
|
|
|
static void cb_collapse(GtkTreeView *widget, GtkTreeIter *iter, GtkTreePath *path, gTreeView *control)
|
|
{
|
|
if (control->locked())
|
|
return;
|
|
|
|
char *key = control->find(path);
|
|
control->refreshExpanded(key, false);
|
|
control->emit(SIGNAL(control->onCollapse), key);
|
|
}
|
|
|
|
static void cb_remove(gTree *tree, char *key)
|
|
{
|
|
gTreeView *view = (gTreeView *)tree->view;
|
|
// This signal ignores locks
|
|
if (view->onRemove)
|
|
(*(view->onRemove))(view, key);
|
|
}
|
|
|
|
gTreeView::gTreeView(gContainer *parent, bool list) : gControl(parent)
|
|
{
|
|
GtkTreeSelection *sel;
|
|
|
|
g_typ=Type_gTreeView;
|
|
use_base = true;
|
|
|
|
tree = new gTree(this);
|
|
tree->addColumn();
|
|
tree->setHeaders(false);
|
|
tree->onRemove = cb_remove;
|
|
|
|
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree->widget), true);
|
|
|
|
treeview = tree->widget;
|
|
realizeScrolledWindow(treeview, true);
|
|
// BM: must occurs before!
|
|
g_signal_connect(G_OBJECT(treeview),"button-press-event",G_CALLBACK(cb_button_press),(gpointer)this);
|
|
realize(false);
|
|
|
|
setMode(SELECT_SINGLE);
|
|
setBorder(true);
|
|
|
|
onActivate = NULL;
|
|
onSelect = NULL;
|
|
onClick = NULL;
|
|
onCollapse = NULL;
|
|
onExpand = NULL;
|
|
onRemove = NULL;
|
|
onRename = NULL;
|
|
onCancel = NULL;
|
|
onCompare = NULL;
|
|
|
|
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree->widget));
|
|
|
|
g_signal_connect(G_OBJECT(treeview),"row-activated",G_CALLBACK(cb_activate),(gpointer)this);
|
|
g_signal_connect(G_OBJECT(sel),"changed",G_CALLBACK(cb_select),(gpointer)this);
|
|
g_signal_connect(G_OBJECT(treeview),"row-expanded",G_CALLBACK(cb_expand),(gpointer)this);
|
|
g_signal_connect(G_OBJECT(treeview),"row-collapsed",G_CALLBACK(cb_collapse),(gpointer)this);
|
|
g_signal_connect(G_OBJECT(treeview),"cursor-changed",G_CALLBACK(cb_click),(gpointer)this);
|
|
}
|
|
|
|
gTreeView::~gTreeView()
|
|
{
|
|
delete tree;
|
|
}
|
|
|
|
|
|
bool gTreeView::add(char *key,char *text,gPicture *pic,char *after,char *parent, bool before)
|
|
{
|
|
gTreeRow *row;
|
|
gTreeCell *cell;
|
|
|
|
row = tree->addRow(key,parent,after,before);
|
|
|
|
if (!row) return false;
|
|
|
|
cell = row->get(0);
|
|
if (cell)
|
|
{
|
|
cell->setText(text);
|
|
cell->setPicture(pic);
|
|
tree->sortLater();
|
|
}
|
|
|
|
//if ( tree->rowCount()==1) tree->setCursor(key);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool gTreeView::remove(char *key)
|
|
{
|
|
return tree->removeRow(key);
|
|
}
|
|
|
|
bool gTreeView::exists(char *key)
|
|
{
|
|
return tree->rowExists(key);
|
|
}
|
|
|
|
int gTreeView::count()
|
|
{
|
|
return tree->rowCount();
|
|
}
|
|
|
|
int gTreeView::mode()
|
|
{
|
|
GtkTreeSelection *sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(tree->widget));
|
|
|
|
switch (gtk_tree_selection_get_mode (sel))
|
|
{
|
|
case GTK_SELECTION_NONE: return 0;
|
|
case GTK_SELECTION_SINGLE: return 1;
|
|
default: return 2;
|
|
}
|
|
}
|
|
|
|
void gTreeView::setMode(int vl)
|
|
{
|
|
GtkTreeSelection *sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(tree->widget));
|
|
|
|
switch (vl)
|
|
{
|
|
case SELECT_NONE:
|
|
gtk_tree_selection_set_mode(sel,GTK_SELECTION_NONE); break;
|
|
case SELECT_SINGLE:
|
|
gtk_tree_selection_set_mode(sel,GTK_SELECTION_SINGLE); break;
|
|
case SELECT_MULTIPLE:
|
|
gtk_tree_selection_set_mode(sel,GTK_SELECTION_MULTIPLE); break;
|
|
}
|
|
}
|
|
|
|
int gTreeView::visibleWidth()
|
|
{
|
|
return tree->visibleWidth();
|
|
}
|
|
|
|
int gTreeView::visibleHeight()
|
|
{
|
|
return tree->visibleHeight();
|
|
}
|
|
|
|
|
|
char* gTreeView::itemText(char *key)
|
|
{
|
|
return itemText(key, 0);
|
|
}
|
|
|
|
void gTreeView::setItemText(char *key, const char *vl)
|
|
{
|
|
setItemText(key, 0, vl);
|
|
}
|
|
|
|
int gTreeView::itemChildren(char *key)
|
|
{
|
|
gTreeRow *row;
|
|
|
|
if (!key) return 0;
|
|
row=tree->getRow(key);
|
|
if (!row) return 0;
|
|
return row->children();
|
|
|
|
}
|
|
|
|
gPicture* gTreeView::itemPicture(char *key)
|
|
{
|
|
gTreeRow *row;
|
|
|
|
if (!key) return NULL;
|
|
row=tree->getRow(key);
|
|
if (!row) return NULL;
|
|
|
|
return row->get(0)->picture();
|
|
}
|
|
|
|
void gTreeView::setItemPicture(char *key,gPicture *vl)
|
|
{
|
|
gTreeRow *row;
|
|
|
|
if (!key) return;
|
|
row=tree->getRow(key);
|
|
if (!row) return;
|
|
row->get(0)->setPicture(vl);
|
|
row->update();
|
|
}
|
|
|
|
bool gTreeView::isItemSelected(char *key)
|
|
{
|
|
if (!key) return false;
|
|
return tree->rowSelected(key);
|
|
}
|
|
|
|
void gTreeView::setItemSelected(char *key, bool vl)
|
|
{
|
|
if (key)
|
|
{
|
|
if (vl && mode() == SELECT_SINGLE)
|
|
tree->setCursor(key);
|
|
tree->setRowSelected(key, vl);
|
|
}
|
|
}
|
|
|
|
char* gTreeView::firstItem(char *parent)
|
|
{
|
|
if (!parent)
|
|
return tree->firstRow();
|
|
|
|
gTreeRow *row=tree->getRow(parent);
|
|
if (!row) return NULL;
|
|
return row->child();
|
|
}
|
|
|
|
char* gTreeView::lastItem(char *parent)
|
|
{
|
|
if (!parent)
|
|
return tree->lastRow();
|
|
|
|
gTreeRow *row=tree->getRow(parent);
|
|
if (!row) return NULL;
|
|
return row->last();
|
|
}
|
|
|
|
char* gTreeView::nextItem(char *vl)
|
|
{
|
|
gTreeRow *row=tree->getRow(vl);
|
|
if (!row) return NULL;
|
|
return row->next();
|
|
}
|
|
|
|
char* gTreeView::prevItem(char *vl)
|
|
{
|
|
gTreeRow *row=tree->getRow(vl);
|
|
if (!row) return NULL;
|
|
return row->prev();
|
|
}
|
|
|
|
char* gTreeView::parentItem(char *vl)
|
|
{
|
|
gTreeRow *row=tree->getRow(vl);
|
|
if (!row) return NULL;
|
|
return row->parent();
|
|
}
|
|
|
|
char* gTreeView::aboveItem(char *vl)
|
|
{
|
|
gTreeRow *row=tree->getRow(vl);
|
|
if (!row) return NULL;
|
|
return row->above();
|
|
}
|
|
|
|
char* gTreeView::belowItem(char *vl)
|
|
{
|
|
gTreeRow *row=tree->getRow(vl);
|
|
if (!row) return NULL;
|
|
return row->below();
|
|
}
|
|
|
|
|
|
char* gTreeView::find(int x, int y)
|
|
{
|
|
GtkTreePath *path;
|
|
|
|
if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tree->widget), x, y, &path, NULL, NULL, NULL))
|
|
return tree->pathToKey(path);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool gTreeView::isItemExpanded(char *key)
|
|
{
|
|
return (*tree)[key]->isExpanded();
|
|
}
|
|
|
|
void gTreeView::setItemExpanded(char *key, bool ex)
|
|
{
|
|
gTreeRow *row = (*tree)[key];
|
|
if (row->isExpanded() != ex)
|
|
row->setExpanded(ex);
|
|
}
|
|
|
|
void gTreeView::setColumnCount(int ncol)
|
|
{
|
|
while (columnCount() < ncol)
|
|
tree->addColumn();
|
|
while (columnCount() > ncol)
|
|
tree->removeColumn();
|
|
}
|
|
|
|
char *gTreeView::columnText(int col)
|
|
{
|
|
return tree->columnName(col);
|
|
}
|
|
|
|
void gTreeView::setColumnText(int col, char *text)
|
|
{
|
|
tree->setColumnName(col, text);
|
|
}
|
|
|
|
char *gTreeView::itemText(char *key, int col)
|
|
{
|
|
gTreeRow *row;
|
|
gTreeCell *cell;
|
|
|
|
if (!key) return NULL;
|
|
row=tree->getRow(key);
|
|
if (!row) return NULL;
|
|
cell = row->get(col);
|
|
if (!cell) return NULL;
|
|
return cell->text();
|
|
}
|
|
|
|
void gTreeView::setItemText(char *key, int col, const char *text)
|
|
{
|
|
gTreeRow *row;
|
|
gTreeCell *cell;
|
|
|
|
if (!key) return;
|
|
row=tree->getRow(key);
|
|
if (!row) return;
|
|
cell = row->get(col);
|
|
if (!cell) return;
|
|
|
|
cell->setText(text);
|
|
if (col == getSortColumn())
|
|
tree->sortLater();
|
|
|
|
row->update();
|
|
}
|
|
|
|
void gTreeView::refreshExpanded(char *parent, bool ex)
|
|
{
|
|
char *key;
|
|
gTreeRow *row;
|
|
|
|
//fprintf(stderr, "refreshExpanded: %s %d\n", parent, ex);
|
|
|
|
row = tree->getRow(parent);
|
|
row->updateExpanded(ex);
|
|
if (!row->isExpanded())
|
|
return;
|
|
|
|
key = tree->getRow(parent)->child();
|
|
if (!key)
|
|
return;
|
|
|
|
while (key)
|
|
{
|
|
//fprintf(stderr, "check: %s\n", key);
|
|
row = tree->getRow(key);
|
|
if (row->isExpanded())
|
|
{
|
|
row->setExpanded();
|
|
refreshExpanded(key, true);
|
|
}
|
|
key = row->next();
|
|
}
|
|
}
|
|
|
|
|
|
void gTreeView::moveItemFirst(char *key)
|
|
{
|
|
(*tree)[key]->moveFirst();
|
|
}
|
|
|
|
void gTreeView::moveItemLast(char *key)
|
|
{
|
|
(*tree)[key]->moveLast();
|
|
}
|
|
|
|
void gTreeView::moveItemBefore(char *key, char *before)
|
|
{
|
|
(*tree)[key]->moveBefore(before);
|
|
}
|
|
|
|
void gTreeView::moveItemAfter(char *key, char *after)
|
|
{
|
|
(*tree)[key]->moveAfter(after);
|
|
}
|
|
|
|
char *gTreeView::intern(char *key)
|
|
{
|
|
gTreeRow *row = (*tree)[key];
|
|
return row ? row->key() : NULL;
|
|
}
|
|
|
|
int gTreeView::clientWidth()
|
|
{
|
|
GtkAdjustment* Adj;
|
|
|
|
Adj=gtk_scrolled_window_get_hadjustment(_scroll);
|
|
return (int)Adj->page_size;
|
|
}
|
|
|
|
int gTreeView::clientHeight()
|
|
{
|
|
GtkAdjustment* Adj;
|
|
|
|
Adj=gtk_scrolled_window_get_vadjustment(_scroll);
|
|
return (int)Adj->page_size;
|
|
}
|
|
|