wip
git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@755 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
parent
d722d9da58
commit
5b0a5235cc
8 changed files with 304 additions and 6 deletions
|
|
@ -49,5 +49,6 @@
|
||||||
#include <Mw/Widget/RadioBox.h>
|
#include <Mw/Widget/RadioBox.h>
|
||||||
#include <Mw/Widget/Separator.h>
|
#include <Mw/Widget/Separator.h>
|
||||||
#include <Mw/Widget/ComboBox.h>
|
#include <Mw/Widget/ComboBox.h>
|
||||||
|
#include <Mw/Widget/TreeView.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@ typedef struct _MwEntry* MwEntry;
|
||||||
typedef struct _MwViewport* MwViewport;
|
typedef struct _MwViewport* MwViewport;
|
||||||
typedef struct _MwListBox* MwListBox;
|
typedef struct _MwListBox* MwListBox;
|
||||||
typedef struct _MwComboBox* MwComboBox;
|
typedef struct _MwComboBox* MwComboBox;
|
||||||
|
typedef struct _MwTreeView* MwTreeView;
|
||||||
typedef struct _MwListBoxEntry MwListBoxEntry;
|
typedef struct _MwListBoxEntry MwListBoxEntry;
|
||||||
|
typedef struct _MwTreeViewEntry MwTreeViewEntry;
|
||||||
typedef struct _MwDirectoryEntry MwDirectoryEntry;
|
typedef struct _MwDirectoryEntry MwDirectoryEntry;
|
||||||
typedef struct _MwListBoxPacket MwListBoxPacket;
|
typedef struct _MwListBoxPacket MwListBoxPacket;
|
||||||
#ifdef _MILSKO
|
#ifdef _MILSKO
|
||||||
|
|
@ -124,7 +126,7 @@ struct _MwListBox {
|
||||||
MwWidget vscroll;
|
MwWidget vscroll;
|
||||||
MwWidget frame;
|
MwWidget frame;
|
||||||
MwListBoxEntry* list;
|
MwListBoxEntry* list;
|
||||||
int selected;
|
int selected;
|
||||||
unsigned long click_time;
|
unsigned long click_time;
|
||||||
int pressed;
|
int pressed;
|
||||||
int* width;
|
int* width;
|
||||||
|
|
@ -137,6 +139,19 @@ struct _MwComboBox {
|
||||||
MwWidget listbox;
|
MwWidget listbox;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _MwTreeViewEntry {
|
||||||
|
char* label;
|
||||||
|
MwLLPixmap pixmap;
|
||||||
|
MwTreeViewEntry* tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MwTreeView {
|
||||||
|
MwWidget frame;
|
||||||
|
MwWidget vscroll;
|
||||||
|
int changed;
|
||||||
|
MwTreeViewEntry* tree;
|
||||||
|
};
|
||||||
|
|
||||||
struct _MwDirectoryEntry {
|
struct _MwDirectoryEntry {
|
||||||
char* name;
|
char* name;
|
||||||
int type;
|
int type;
|
||||||
|
|
|
||||||
26
include/Mw/Widget/TreeView.h
Normal file
26
include/Mw/Widget/TreeView.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/*!
|
||||||
|
* @file Mw/Widget/TreeView.h
|
||||||
|
* @brief TreeView widget
|
||||||
|
*/
|
||||||
|
#ifndef __MW_WIDGET_TREEVIEW_H__
|
||||||
|
#define __MW_WIDGET_TREEVIEW_H__
|
||||||
|
|
||||||
|
#include <Mw/MachDep.h>
|
||||||
|
#include <Mw/TypeDefs.h>
|
||||||
|
#include <Mw/Core.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief TreeView widget class
|
||||||
|
*/
|
||||||
|
MWDECL MwClass MwTreeViewClass;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -63,6 +63,7 @@ new_object("src/widget/radiobox.c");
|
||||||
new_object("src/widget/scrollbar.c");
|
new_object("src/widget/scrollbar.c");
|
||||||
new_object("src/widget/separator.c");
|
new_object("src/widget/separator.c");
|
||||||
new_object("src/widget/submenu.c");
|
new_object("src/widget/submenu.c");
|
||||||
|
new_object("src/widget/treeview.c");
|
||||||
new_object("src/widget/viewport.c");
|
new_object("src/widget/viewport.c");
|
||||||
new_object("src/widget/window.c");
|
new_object("src/widget/window.c");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -532,7 +532,7 @@ void MwHideCursor(MwWidget handle) {
|
||||||
|
|
||||||
void MwDispatchUserHandler(MwWidget handle, const char* key, void* handler_data) {
|
void MwDispatchUserHandler(MwWidget handle, const char* key, void* handler_data) {
|
||||||
int ind = shgeti(handle->handler, key);
|
int ind = shgeti(handle->handler, key);
|
||||||
int p = handle->prop_event;
|
int p = handle->prop_event;
|
||||||
if(ind == -1) return;
|
if(ind == -1) return;
|
||||||
if(handle->destroyed) return;
|
if(handle->destroyed) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,8 @@ static void listbox_activate(MwWidget handle, void* user, void* client) {
|
||||||
(void)user;
|
(void)user;
|
||||||
|
|
||||||
MwSetInteger(handle->parent, MwNvalue, *(int*)client);
|
MwSetInteger(handle->parent, MwNvalue, *(int*)client);
|
||||||
cb->opened = 0;
|
cb->opened = 0;
|
||||||
cb->listbox = NULL;
|
cb->listbox = NULL;
|
||||||
|
|
||||||
MwForceRender(handle->parent);
|
MwForceRender(handle->parent);
|
||||||
|
|
||||||
|
|
@ -195,7 +195,7 @@ MwClassRec MwComboBoxClassRec = {
|
||||||
draw, /* draw */
|
draw, /* draw */
|
||||||
click, /* click */
|
click, /* click */
|
||||||
NULL, /* parent_resize */
|
NULL, /* parent_resize */
|
||||||
prop_change, /* prop_change */
|
prop_change, /* prop_change */
|
||||||
NULL, /* mouse_move */
|
NULL, /* mouse_move */
|
||||||
MwForceRender2, /* mouse_up */
|
MwForceRender2, /* mouse_up */
|
||||||
MwForceRender2, /* mouse_down */
|
MwForceRender2, /* mouse_down */
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ static int create(MwWidget handle) {
|
||||||
|
|
||||||
MwSetInteger(handle, MwNsingleClickSelectable, 0);
|
MwSetInteger(handle, MwNsingleClickSelectable, 0);
|
||||||
MwSetInteger(handle, MwNhasHeading, 0);
|
MwSetInteger(handle, MwNhasHeading, 0);
|
||||||
MwSetInteger(handle, MwNvalue, 0);
|
MwSetInteger(handle, MwNleftPadding, 0);
|
||||||
|
|
||||||
resize(handle);
|
resize(handle);
|
||||||
lb->list = NULL;
|
lb->list = NULL;
|
||||||
|
|
|
||||||
255
src/widget/treeview.c
Normal file
255
src/widget/treeview.c
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
/* $Id$ */
|
||||||
|
#include <Mw/Milsko.h>
|
||||||
|
|
||||||
|
#include "../../external/stb_ds.h"
|
||||||
|
|
||||||
|
static void vscroll_changed(MwWidget handle, void* user, void* call) {
|
||||||
|
MwTreeView tv = handle->parent->internal;
|
||||||
|
|
||||||
|
(void)user;
|
||||||
|
(void)call;
|
||||||
|
|
||||||
|
tv->changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwLLColor text, MwPoint* p, int next, int shift, int* skip, int* shared){
|
||||||
|
int i;
|
||||||
|
MwPoint l[2];
|
||||||
|
if((*skip) > 0){
|
||||||
|
(*skip)--;
|
||||||
|
}else if((*shared) < (MwGetInteger(handle, MwNheight) / MwTextHeight(handle, "M"))){
|
||||||
|
p->x += shift;
|
||||||
|
p->y += MwTextHeight(handle, "M") / 2;
|
||||||
|
|
||||||
|
if(shift > 0){
|
||||||
|
l[0] = *p;
|
||||||
|
l[0].x -= 16 / 2;
|
||||||
|
l[1] = *p;
|
||||||
|
MwLLLine(handle->lowlevel, &l[0], text);
|
||||||
|
|
||||||
|
l[0] = *p;
|
||||||
|
l[0].x -= 16 / 2;
|
||||||
|
l[1] = l[0];
|
||||||
|
l[0].y -= MwTextHeight(handle, "M") / 2;
|
||||||
|
if(next){
|
||||||
|
l[1].y += MwTextHeight(handle, "M") / 2;
|
||||||
|
}
|
||||||
|
MwLLLine(handle->lowlevel, &l[0], text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tree->pixmap != NULL){
|
||||||
|
MwRect r;
|
||||||
|
|
||||||
|
r.height = MwTextHeight(handle, "M");
|
||||||
|
r.width = r.height * tree->pixmap->common.width / tree->pixmap->common.height;
|
||||||
|
r.x = p->x;
|
||||||
|
r.y = p->y - MwTextHeight(handle, "M") / 2;
|
||||||
|
|
||||||
|
MwLLDrawPixmap(handle->lowlevel, &r, tree->pixmap);
|
||||||
|
}
|
||||||
|
p->x += MwGetInteger(handle->parent, MwNleftPadding);
|
||||||
|
MwDrawText(handle, p, tree->label, 0, MwALIGNMENT_BEGINNING, text);
|
||||||
|
p->x -= MwGetInteger(handle->parent, MwNleftPadding);
|
||||||
|
|
||||||
|
p->y += MwTextHeight(handle, "M") / 2;
|
||||||
|
p->x -= shift;
|
||||||
|
|
||||||
|
(*shared)++;
|
||||||
|
}
|
||||||
|
for(i = 0; i < arrlen(tree->tree); i++){
|
||||||
|
l[0] = *p;
|
||||||
|
l[0].x += shift + 16 / 2;
|
||||||
|
l[0].y += MwTextHeight(handle, "M") / 2;
|
||||||
|
|
||||||
|
recursion(handle, &tree->tree[i], text, p, i != (arrlen(tree->tree) - 1) ? 1 : 0, shift+16, skip, shared);
|
||||||
|
|
||||||
|
l[1] = *p;
|
||||||
|
l[1].x += shift + 16 / 2;
|
||||||
|
|
||||||
|
if(i != (arrlen(tree->tree) - 1)) MwLLLine(handle->lowlevel, &l[0], text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void frame_draw(MwWidget handle) {
|
||||||
|
MwRect r;
|
||||||
|
MwTreeView tv = handle->parent->internal;
|
||||||
|
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
|
||||||
|
MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground));
|
||||||
|
MwPoint p;
|
||||||
|
int shared = 0;
|
||||||
|
int i;
|
||||||
|
int skip = MwGetInteger(tv->vscroll, MwNvalue) * (MwGetInteger(tv->vscroll, MwNmaxValue) - MwGetInteger(tv->vscroll, MwNareaShown)) / MwGetInteger(tv->vscroll, MwNmaxValue);
|
||||||
|
|
||||||
|
r.x = 0;
|
||||||
|
r.y = 0;
|
||||||
|
r.width = MwGetInteger(handle, MwNwidth);
|
||||||
|
r.height = MwGetInteger(handle, MwNheight);
|
||||||
|
|
||||||
|
p.x = MwDefaultBorderWidth(handle);
|
||||||
|
p.y = MwDefaultBorderWidth(handle);
|
||||||
|
|
||||||
|
for(i = 0; i < arrlen(tv->tree); i++){
|
||||||
|
if(shared > (r.height / MwTextHeight(handle, "M"))) break;
|
||||||
|
recursion(handle, &tv->tree[i], text, &p, 0, 0, &skip, &shared);
|
||||||
|
}
|
||||||
|
|
||||||
|
MwDrawFrame(handle, &r, base, 1);
|
||||||
|
|
||||||
|
MwLLFreeColor(text);
|
||||||
|
MwLLFreeColor(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int recursive_length(MwTreeViewEntry* e){
|
||||||
|
int l = 0;
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < arrlen(e); i++){
|
||||||
|
l += recursive_length(e->tree);
|
||||||
|
l++;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resize(MwWidget handle) {
|
||||||
|
MwTreeView tv = handle->internal;
|
||||||
|
int w = MwGetInteger(handle, MwNwidth);
|
||||||
|
int h = MwGetInteger(handle, MwNheight);
|
||||||
|
int ih = 0;
|
||||||
|
|
||||||
|
if(tv->vscroll == NULL) {
|
||||||
|
tv->vscroll = MwCreateWidget(MwScrollBarClass, "vscroll", handle, w - 16, 0, 16, h);
|
||||||
|
MwAddUserHandler(tv->vscroll, MwNchangedHandler, vscroll_changed, NULL);
|
||||||
|
} else {
|
||||||
|
MwVaApply(tv->vscroll,
|
||||||
|
MwNx, w - 16,
|
||||||
|
MwNy, 0,
|
||||||
|
MwNwidth, 16,
|
||||||
|
MwNheight, h,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(tv->frame == NULL) {
|
||||||
|
tv->frame = MwVaCreateWidget(MwFrameClass, "frame", handle, 0, 0, w - 16, h,
|
||||||
|
MwNhasBorder, 1,
|
||||||
|
MwNinverted, 1,
|
||||||
|
NULL);
|
||||||
|
tv->frame->draw_inject = frame_draw;
|
||||||
|
} else {
|
||||||
|
MwVaApply(tv->frame,
|
||||||
|
MwNx, 0,
|
||||||
|
MwNy, 0,
|
||||||
|
MwNwidth, w - 16,
|
||||||
|
MwNheight, h,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ih = recursive_length(tv->tree);
|
||||||
|
if(ih == 0) ih = 1;
|
||||||
|
|
||||||
|
MwVaApply(tv->vscroll,
|
||||||
|
MwNareaShown, h / MwTextHeight(handle, "M"),
|
||||||
|
MwNmaxValue, ih,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create(MwWidget handle) {
|
||||||
|
MwTreeView tv = malloc(sizeof(*tv));
|
||||||
|
MwTreeViewEntry e;
|
||||||
|
int i, j, k, l, c = 0;
|
||||||
|
MwLLPixmap p = MwLoadIcon(handle, MwIconFile);
|
||||||
|
memset(tv, 0, sizeof(*tv));
|
||||||
|
|
||||||
|
for(i = 0; i < 10; i++){
|
||||||
|
char str[32];
|
||||||
|
|
||||||
|
sprintf(str, "hello %d", ++c);
|
||||||
|
|
||||||
|
e.label = MwStringDupliacte(str);
|
||||||
|
e.pixmap = p;
|
||||||
|
e.tree = NULL;
|
||||||
|
for(j = 0; j < 3; j++){
|
||||||
|
MwTreeViewEntry e2;
|
||||||
|
sprintf(str, "hello %d", ++c);
|
||||||
|
e2.label = MwStringDupliacte(str);
|
||||||
|
e2.pixmap = p;
|
||||||
|
e2.tree = NULL;
|
||||||
|
for(k = 0; k < 3; k++){
|
||||||
|
MwTreeViewEntry e3;
|
||||||
|
sprintf(str, "hello %d", ++c);
|
||||||
|
e3.label = MwStringDupliacte(str);
|
||||||
|
e3.pixmap = p;
|
||||||
|
e3.tree = NULL;
|
||||||
|
for(l = 0; l < 3; l++){
|
||||||
|
MwTreeViewEntry e4;
|
||||||
|
sprintf(str, "hello %d", ++c);
|
||||||
|
e4.label = MwStringDupliacte(str);
|
||||||
|
e4.pixmap = p;
|
||||||
|
e4.tree = NULL;
|
||||||
|
arrput(e3.tree, e4);
|
||||||
|
}
|
||||||
|
arrput(e2.tree, e3);
|
||||||
|
}
|
||||||
|
arrput(e.tree, e2);
|
||||||
|
}
|
||||||
|
arrput(tv->tree, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->internal = tv;
|
||||||
|
|
||||||
|
MwSetDefault(handle);
|
||||||
|
|
||||||
|
MwSetInteger(handle, MwNsingleClickSelectable, 0);
|
||||||
|
MwSetInteger(handle, MwNleftPadding, 16);
|
||||||
|
|
||||||
|
resize(handle);
|
||||||
|
tv->changed = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy(MwWidget handle) {
|
||||||
|
free(handle->internal);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw(MwWidget handle) {
|
||||||
|
MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground));
|
||||||
|
MwRect r;
|
||||||
|
|
||||||
|
r.x = 0;
|
||||||
|
r.y = 0;
|
||||||
|
r.width = MwGetInteger(handle, MwNwidth);
|
||||||
|
r.height = MwGetInteger(handle, MwNheight);
|
||||||
|
MwDrawRect(handle, &r, c);
|
||||||
|
|
||||||
|
MwLLFreeColor(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prop_change(MwWidget handle, const char* prop) {
|
||||||
|
if(strcmp(prop, MwNwidth) == 0 || strcmp(prop, MwNheight) == 0) resize(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tick(MwWidget handle) {
|
||||||
|
MwTreeView tv = handle->internal;
|
||||||
|
|
||||||
|
if(tv->changed) {
|
||||||
|
tv->changed = 0;
|
||||||
|
MwForceRender(tv->frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MwClassRec MwTreeViewClassRec = {
|
||||||
|
create, /* create */
|
||||||
|
destroy, /* destroy */
|
||||||
|
draw, /* draw */
|
||||||
|
NULL, /* click */
|
||||||
|
NULL, /* parent_resize */
|
||||||
|
prop_change, /* prop_change */
|
||||||
|
NULL, /* mouse_move */
|
||||||
|
NULL, /* mouse_up */
|
||||||
|
NULL, /* mouse_down */
|
||||||
|
NULL, /* key */
|
||||||
|
NULL, /* execute */
|
||||||
|
tick, /* tick */
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL};
|
||||||
|
MwClass MwTreeViewClass = &MwTreeViewClassRec;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue