From f016f09792e289eab1fa39f23a793b9fd7606f61 Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Thu, 7 Apr 2005 22:46:43 +0000 Subject: [PATCH] Add list widget + cleanups --- ChangeLog | 24 +++ Makefile | 8 +- cltr-events.c | 13 +- cltr-list.c | 536 +++++++++++++++++++++------------------------- cltr-list.h | 34 +++ cltr-photo-grid.c | 347 ++++++++++++++++-------------- cltr-texture.c | 4 +- cltr-widget.c | 26 ++- cltr-window.c | 42 +++- cltr-window.h | 11 +- cltr.c | 20 +- cltr.h | 11 + pixbuf.c | 18 ++ pixbuf.h | 9 + 14 files changed, 619 insertions(+), 484 deletions(-) create mode 100644 cltr-list.h diff --git a/ChangeLog b/ChangeLog index 66459f466..363c991d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2005-04-07 mallum,,, + + * Makefile: + * cltr-events.c: (cltr_main_loop): + * cltr-list.c: + * cltr-list.h: + Add list widget + * cltr-photo-grid.c: (cltr_photo_grid_cell_new), + (cltr_photo_grid_append_cell), (ctrl_photo_grid_cell_to_coords), + (ctrl_photo_grid_get_zoomed_coords), (cltr_photo_grid_idle_cb), + (cltr_photo_grid_navigate), (cltr_photo_grid_activate_cell), + (cltr_photo_grid_update_visual_state), (cltr_photo_grid_paint), + (cltr_photo_grid_show), (cltr_photo_grid_new): + * cltr-texture.c: + * cltr-widget.c: + * cltr-window.c: (cltr_window_new), (cltr_window_show), + (cltr_window_handle_xevent): + * cltr-window.h: + * cltr.c: (main): + * cltr.h: + * pixbuf.c: (pixbuf_copy): + * pixbuf.h: + Cleanups + 2005-04-03 mallum,,, * Makefile: diff --git a/Makefile b/Makefile index 2330ef5ea..0addf3f84 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,9 @@ OBJS=cltr.o pixbuf.o util.o fonts.o \ cltr-widget.o \ cltr-events.o \ cltr-window.o \ - cltr-photo-grid.o + cltr-photo-grid.o \ + cltr-list.o \ + cltr-scratch.o # cltr-photo-grid.o @@ -24,7 +26,9 @@ $(OBJS): pixbuf.h util.h fonts.h \ cltr-texture.h \ cltr-widget.h \ cltr-window.h \ - cltr-photo-grid.h + cltr-photo-grid.h \ + cltr-list.h \ + cltr-scratch.h #cltr-photo-grid.h diff --git a/cltr-events.c b/cltr-events.c index 15425acaa..c03f7a25a 100644 --- a/cltr-events.c +++ b/cltr-events.c @@ -160,10 +160,15 @@ cltr_main_loop() CltrWidget *widget = NULL; CltrWindow *win = CLTR_WINDOW(ctx->window); - while ((widget = g_queue_pop_head(ctx->internal_event_q)) != NULL) - { - cltr_widget_paint(widget); - } + /* Empty the queue */ + while (g_queue_pop_head(ctx->internal_event_q) != NULL) ; + + /* Repaint everything visible from window down - URG. + * GL workings make it difficult to paint single part with + * layering etc.. + * Is this really bad ? time will tell... + */ + cltr_widget_paint(CLTR_WIDGET(win)); /* Swap Buffers */ glXSwapBuffers(ctx->xdpy, cltr_window_xwin(win)); diff --git a/cltr-list.c b/cltr-list.c index e2189cf81..fff6cbbbf 100644 --- a/cltr-list.c +++ b/cltr-list.c @@ -1,349 +1,301 @@ -#include -#include -#include -#include -#include +#include "cltr-list.h" +#include "cltr-private.h" -#include +#define ANIM_FPS 200 +#define FPS_TO_TIMEOUT(t) (1000/(t)) -#include -#include - -#include "pixbuf.h" -#include "fonts.h" - -#define TEX_W 1024 /* must be > than frame_w & power of 2 */ -#define TEX_H 1024 -/* - * - */ - -#define WINW 640 -#define WINH 480 - -#define NBOXITEMS 10 - -#define NUMRECTS 4 -#define MAXSCALE 2 -#define MAXDIST (WINH) -#define MAXH (WINH/NUMRECTS) -#define MAXW (WINW - 20) - -#ifndef ABS -#define ABS(a) ((a > 0) ? (a) : -1 * (a)) -#endif - -typedef struct TableWidget TableWidget; - -typedef struct TableWidgetCell TableWidgetCell; - -int ScrollDir = 1; - -struct TableWidget +typedef struct CltrListCell { - int x,y,width,height; - - TableWidgetCell *cells, *active_cell; - - int active_cell_y; + CltrRect rect; + Pixbuf *pixb; + CltrTexture *texture; +} CltrListCell; +struct CltrList +{ + CltrWidget widget; + GList *cells, *active_cell; + int active_cell_y; + int cell_height; + int cell_width; + + CltrListState state; + int scroll_dir; }; -struct TableWidgetCell +static void +cltr_list_show(CltrWidget *widget); + +static gboolean +cltr_list_handle_xevent (CltrWidget *widget, XEvent *xev); + +static void +cltr_list_paint(CltrWidget *widget); + +static float +distfunc(CltrList *list, int d) { - XRectangle rect; - TableWidgetCell *next, *prev; - -}; - - -Display *xdpy; -Window xwin; -XEvent xevent; -GC xgc; -Pixbuf *pix, *pix_orig; - -float -distfunc(TableWidget *table, int d) -{ -/* printf("returning %f\n", (exp((float)d/MAXDIST)/exp(1.0))); */ - int maxdist = table->height; + int maxdist = list->widget.height; d = (maxdist-ABS(d)) ; return ( exp( (float)d/maxdist * 2.0 ) / exp(2.0) ); } -TableWidgetCell* -table_cell_new() +CltrListCell* +cltr_list_cell_new(CltrList *list) { - TableWidgetCell *cell = NULL; + CltrListCell *cell = NULL; + ClutterFont *font; + gchar buf[24]; + PixbufPixel pixel = { 255, 20, 20, 255 }; - cell = malloc(sizeof(TableWidgetCell)); - memset(cell, 0, sizeof(TableWidgetCell)); + font = font_new ("Sans Bold 96"); + + cell = g_malloc0(sizeof(CltrListCell)); + + cell->pixb = pixbuf_new(list->cell_width, list->cell_height); + + pixbuf_fill_rect(cell->pixb, 0, 0, -1, -1, &pixel); + + g_snprintf(&buf[0], 24, "%i %i %i", rand()%10, rand()%10, rand()%10); + + font_draw(font, cell->pixb, buf, 10, 10); + + cell->texture = cltr_texture_new(cell->pixb); return cell; } -TableWidget* -table_new(int n_items) +CltrWidget* +cltr_list_new(int width, + int height, + int cell_width, + int cell_height) { - TableWidget *table = NULL; - TableWidgetCell *last = NULL, *cell = NULL; - int i; + CltrList *list; - table = malloc(sizeof(TableWidget)); - memset(table, 0, sizeof(TableWidget)); + list = g_malloc0(sizeof(CltrList)); + + list->widget.width = width; + list->widget.height = height; + + list->widget.show = cltr_list_show; + list->widget.paint = cltr_list_paint; + + list->cell_height = cell_height; /* maximum */ + list->cell_width = cell_width; /* maximum */ - table->width = WINW; - table->height = WINH; + list->widget.xevent_handler = cltr_list_handle_xevent; - table->active_cell_y = 100; + return CLTR_WIDGET(list); +} + +static void +cltr_list_show(CltrWidget *widget) +{ + CltrList *list = CLTR_LIST(widget); + + int n_items = 50, i; + + list->active_cell_y = 100; for (i=0; icells = g_list_append(list->cells, cltr_list_cell_new(list)); + } + + list->active_cell = g_list_first(list->cells); + + cltr_widget_queue_paint(widget); +} + +static gboolean +cltr_list_handle_xevent (CltrWidget *widget, XEvent *xev) +{ + CltrList *list = CLTR_LIST(widget); + + switch (xev->type) + { + case KeyPress: + { + KeySym kc; + + kc = XKeycodeToKeysym(xev->xkey.display, xev->xkey.keycode, 0); + + switch (kc) + { + case XK_Up: + case XK_KP_Up: + cltr_list_scroll_up(list); + break; + case XK_Down: + case XK_KP_Down: + cltr_list_scroll_down(list); + break; + case XK_Return: + CLTR_DBG("Return"); + break; + case XK_Left: + case XK_KP_Left: + case XK_Right: + case XK_KP_Right: + default: + CLTR_DBG("unhandled keysym"); + } + } + break; + } + + return TRUE; +} + +static void +cltr_list_animate(CltrList *list) +{ + GList *cell_item = NULL; + CltrListCell *next_active = NULL, *cell_top = NULL; + + cell_top = (CltrListCell *)g_list_nth_data(list->cells, 0); + + if (list->state == CLTR_LIST_STATE_SCROLL_UP) + { + cell_item = g_list_previous(list->active_cell); + + if (!cell_item) { - last->next = cell; - cell->prev = last; + list->state = CLTR_LIST_STATE_BROWSE; + return; + } + + next_active = (CltrListCell *)cell_item->data; + + if (next_active->rect.y < list->active_cell_y) + { + cell_top->rect.y += 2; } else - table->cells = table->active_cell = cell; - - last = cell; - } - - table->cells->rect.y = table->active_cell_y; - - return table; -} - -void -table_redraw(TableWidget *table) -{ - TableWidgetCell *cur = table->cells; - int last = table->cells->rect.y; - - glClearColor( 0.0, 0.0, 0.0, 1.0); - glClear (GL_COLOR_BUFFER_BIT); - - while (cur) - { - cur->rect.y = last; - - if (cur->rect.y+cur->rect.height >= 0) { - cur->rect.width = MAXW * distfunc(table, cur->rect.y - table->active_cell_y); - cur->rect.height = MAXH * distfunc(table, cur->rect.y - table->active_cell_y); - - cur->rect.x = (WINW - cur->rect.width)/6; + list->active_cell = cell_item; + list->state = CLTR_LIST_STATE_BROWSE; } + } + else if (list->state == CLTR_LIST_STATE_SCROLL_DOWN) + { + cell_item = g_list_next(list->active_cell); - last = cur->rect.y + cur->rect.height; - - if (last > 0 && cur->rect.y < WINH) /* crappy clip */ + if (!cell_item) { - float tx = 1.0, ty = 1.0, sx, sy; - int x1 = cur->rect.x, x2 = cur->rect.x + cur->rect.width; - int y1 = cur->rect.y, y2 = cur->rect.y + cur->rect.height; - - tx = (float) pix->width / TEX_W; - ty = (float) pix->height / TEX_H; - - - glBegin (GL_QUADS); - glTexCoord2f (tx, ty); glVertex2i (x2, y2); - glTexCoord2f (0, ty); glVertex2i (x1, y2); - glTexCoord2f (0, 0); glVertex2i (x1, y1); - glTexCoord2f (tx, 0); glVertex2i (x2, y1); - glEnd (); - - /* draw with X primitives - XDrawRectangle(xdpy, xwin, xgc, - cur->rect.x, cur->rect.y, - cur->rect.width, cur->rect.height); - - XDrawLine(xdpy, xwin, xgc, - cur->rect.x, cur->rect.y, - cur->rect.x + cur->rect.width, - cur->rect.y + cur->rect.height); - */ + list->state = CLTR_LIST_STATE_BROWSE; + return; + } + + next_active = (CltrListCell *)cell_item->data; + + if (next_active->rect.y > list->active_cell_y) + { + cell_top->rect.y -= 2; + } + else + { + list->active_cell = cell_item; + list->state = CLTR_LIST_STATE_BROWSE; } - - cur = cur->next; } - - glXSwapBuffers(xdpy, xwin); - } - -void -table_scroll_down(TableWidget *table) +gboolean +cltr_list_timeout_cb(gpointer data) { - TableWidgetCell *next_active = table->active_cell->next; + CltrList *list = (CltrList *)data; - if (!next_active) + cltr_list_animate(list); + + cltr_widget_queue_paint(CLTR_WIDGET(list)); + + switch(list->state) { - ScrollDir = 0; - return; + case CLTR_LIST_STATE_SCROLL_UP: + case CLTR_LIST_STATE_SCROLL_DOWN: + return TRUE; + case CLTR_LIST_STATE_LOADING: + case CLTR_LIST_STATE_LOAD_COMPLETE: + case CLTR_LIST_STATE_BROWSE: + default: + return FALSE; } - - while (next_active->rect.y > table->active_cell_y) - { - table->cells->rect.y--; - table_redraw(table); - } - - table->active_cell = next_active; } -void -table_scroll_up(TableWidget *table) +static void +cltr_list_paint(CltrWidget *widget) { - TableWidgetCell *next_active = table->active_cell->prev; + GList *cell_item = NULL; + CltrList *list = CLTR_LIST(widget); + CltrListCell *cell = NULL; - if (!next_active) - return; + int last; - while (next_active->rect.y < table->active_cell_y) - { - table->cells->rect.y++; - table_redraw(table); - } + cell_item = g_list_first(list->cells); + cell = (CltrListCell *)cell_item->data; + last = cell->rect.y; - table->active_cell = next_active; -} + glPushMatrix(); + glEnable(GL_TEXTURE_2D); -int -main(int argc, char **argv) -{ - TableWidget *table; - int i, j, last, offset=0; - XGCValues gcvals; - ClutterFont *font = NULL; - - /* GL */ - GLXContext context; /* OpenGL context */ - GLubyte *texture_data = NULL; - XVisualInfo *vinfo; - static int attributes[] = - { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - 0 - }; - - - - if ((xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL) - { - fprintf(stderr, "%s: Cant open display\n", argv[0]); - exit(-1); - } - - - if ((vinfo = glXChooseVisual(xdpy, DefaultScreen(xdpy), attributes)) == NULL) - { - fprintf(stderr, "Unable to find visual\n"); - exit(-1); - } - - xwin = XCreateSimpleWindow(xdpy, - RootWindow(xdpy, DefaultScreen(xdpy)), - 0, 0, - WINW, WINH, - 0, 0, WhitePixel(xdpy, DefaultScreen(xdpy))); - - gcvals.foreground = BlackPixel(xdpy, DefaultScreen(xdpy)); - gcvals.background = WhitePixel(xdpy, DefaultScreen(xdpy)); - gcvals.line_width = 1; - - xgc = XCreateGC(xdpy, RootWindow(xdpy, DefaultScreen(xdpy)), - GCForeground|GCBackground|GCLineWidth, - &gcvals); - - context = glXCreateContext(xdpy, vinfo, 0, True); - glXMakeCurrent(xdpy, xwin, context); - - glViewport (0, 0, WINW, WINH); - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); - glClearColor (0, 0, 0, 0); - glClearDepth (1.0f); - - glDisable (GL_DEPTH_TEST); - glDepthMask (GL_FALSE); - glDisable (GL_CULL_FACE); - glShadeModel (GL_FLAT); - glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - - // glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - glOrtho (0, WINW, WINH, 0, -1, 1); - - glEnable (GL_TEXTURE_2D); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - texture_data = malloc (TEX_W * TEX_H * 4); - - for (i=0; i < (TEX_W * TEX_H * 4); i++) - texture_data[i] = rand()%255; - - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, - TEX_W, TEX_H, - 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data); - - pix_orig = pixbuf_new_from_file(argv[1]); - - if (!pix_orig) + while (cell_item) { - fprintf(stderr, "image load failed\n"); - exit(-1); - } + cell = (CltrListCell *)cell_item->data; - pix = pixbuf_scale_down(pix_orig, 100, 100); - - /* - font = font_new("Sans Bold 48"); - - font_draw(font, pix, "Hello World\nlove matmoo", 0, 0); - */ - - glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, - (GLsizei)pix->width, - (GLsizei)pix->height, - GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, - pix->data); - - table = table_new(NBOXITEMS); - - table_redraw(table); - - XMapWindow(xdpy, xwin); - - for (;;) - { - XEvent ev; - // XNextEvent(xdpy, &ev); - // XClearWindow(xdpy, xwin); - table_redraw(table); - ScrollDir ? table_scroll_down(table) : table_scroll_up(table); + cell->rect.y = last; + + if (cell->rect.y + cell->rect.height >= 0) + { + cell->rect.width = list->cell_width * distfunc(list, cell->rect.y - list->active_cell_y); + cell->rect.height = list->cell_height * distfunc(list, cell->rect.y - list->active_cell_y); + + /* cell->rect.x = (list->widget.width - cell->rect.width) / 6; */ + cell->rect.x = 0; + } - // scroll_to_next(); - XFlush(xdpy); - sleep(1); + last = cell->rect.y + cell->rect.height; + + if (last > 0 && cell->rect.y < list->widget.width) /* crappy clip */ + { + cltr_texture_render_to_gl_quad(cell->texture, + cltr_rect_x1(cell->rect), + cltr_rect_y1(cell->rect), + cltr_rect_x2(cell->rect), + cltr_rect_y2(cell->rect)); + } + + cell_item = g_list_next(cell_item); } + glDisable(GL_BLEND); + + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); +} + + +void +cltr_list_scroll_down(CltrList *list) +{ + list->state = CLTR_LIST_STATE_SCROLL_DOWN; + + g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), + cltr_list_timeout_cb, list); +} + +void +cltr_list_scroll_up(CltrList *list) +{ + list->state = CLTR_LIST_STATE_SCROLL_UP; + + g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), + cltr_list_timeout_cb, list); } diff --git a/cltr-list.h b/cltr-list.h new file mode 100644 index 000000000..72fdbe2aa --- /dev/null +++ b/cltr-list.h @@ -0,0 +1,34 @@ +#ifndef _HAVE_CLTR_LIST_H +#define _HAVE_CLTR_LIST_H + +#include "cltr.h" + +typedef struct CltrList CltrList; + +#define CLTR_LIST(w) ((CltrList*)(w)) + +typedef enum CltrListState +{ + CLTR_LIST_STATE_LOADING , + CLTR_LIST_STATE_LOAD_COMPLETE , + CLTR_LIST_STATE_BROWSE , + CLTR_LIST_STATE_SCROLL_UP , + CLTR_LIST_STATE_SCROLL_DOWN +} +CltrListState; + + +CltrWidget* +cltr_list_new(int width, + int height, + int cell_width, + int cell_height); + +void +cltr_list_scroll_down(CltrList *list); + +void +cltr_list_scroll_up(CltrList *list); + + +#endif diff --git a/cltr-photo-grid.c b/cltr-photo-grid.c index b2676b8e3..55f6c34dd 100644 --- a/cltr-photo-grid.c +++ b/cltr-photo-grid.c @@ -43,7 +43,7 @@ struct CltrPhotoGrid int n_rows; int n_cols; - int row_offset; /* for scrolling */ + int row_offset; /* where is the first visible row. */ int cell_width; int cell_height; @@ -53,18 +53,22 @@ struct CltrPhotoGrid /* animation / zoom etc stuff */ - int anim_n_steps, anim_step; + /* current anim frame position */ + int anim_n_steps, anim_step; - float zoom_min, zoom_max, zoom_step; + /* start / end points for animations */ + float zoom_min, zoom_max, zoom_step; + float view_min_x, view_max_x, view_min_y, view_max_y; + float scroll_dist; + + /* Values calucated from above for setting up the GL tranforms and 'view' */ + float paint_trans_x, paint_trans_y, paint_zoom; + int paint_start_y; + GList *paint_cell_item; - float view_min_x, view_max_x, view_min_y, view_max_y; - float scroll_dist; CltrPhotoGridState state; - - int scroll_state, scroll_step; /* urg */ - }; static void @@ -76,6 +80,9 @@ cltr_photo_grid_handle_xevent (CltrWidget *widget, XEvent *xev); static void cltr_photo_grid_show(CltrWidget *widget); +static void +cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid); + /* this likely shouldn'y go here */ static GMutex *Mutex_GRID = NULL; @@ -181,8 +188,6 @@ cltr_photo_grid_append_cell(CltrPhotoGrid *grid, CltrPhotoGridCell *cell) { grid->cells_tail = g_list_append(grid->cells_tail, cell); - - } /* relative */ @@ -196,8 +201,6 @@ ctrl_photo_grid_cell_to_coords(CltrPhotoGrid *grid, idx = g_list_position(grid->cells_tail, cell); - /* idx -= (grid->row_offset * grid->n_cols); */ - *y = idx / grid->n_cols; *x = idx % grid->n_cols; @@ -218,7 +221,6 @@ ctrl_photo_grid_get_zoomed_coords(CltrPhotoGrid *grid, *tx = (float)grid->cell_width * (grid->zoom_max) * x * -1.0; *ty = (float)grid->cell_height * (grid->zoom_max) * y * -1.0; - } static gboolean @@ -252,6 +254,8 @@ cltr_photo_grid_idle_cb(gpointer data) { CltrPhotoGrid *grid = (CltrPhotoGrid *)data; + cltr_photo_grid_update_visual_state(grid); + cltr_widget_queue_paint(CLTR_WIDGET(grid)); switch(grid->state) @@ -334,11 +338,6 @@ cltr_photo_grid_navigate(CltrPhotoGrid *grid, { grid->state = CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE; - /* - XXX view_min|max should be view_start|end - - */ - grid->view_min_x = grid->view_max_x; grid->view_min_y = grid->view_max_y ; grid->anim_step = 0; @@ -382,11 +381,8 @@ cltr_photo_grid_activate_cell(CltrPhotoGrid *grid) g_timeout_add(FPS_TO_TIMEOUT(ANIM_FPS), cltr_photo_grid_idle_cb, grid); } - - /* que a draw ? */ } - gpointer cltr_photo_grid_populate(gpointer data) { @@ -465,24 +461,147 @@ cltr_photo_grid_populate(gpointer data) return NULL; } +static void +cltr_photo_grid_update_visual_state(CltrPhotoGrid *grid) +{ + int view_x_diff = grid->view_max_x - grid->view_min_x; + int view_y_diff = grid->view_max_y - grid->view_min_y; + int zoom_diff = grid->zoom_max - grid->zoom_min; + int row_offset_h = grid->row_offset * grid->cell_height; + + /* Default states ( zoomed out ) */ + grid->paint_zoom = grid->zoom_min; + grid->paint_trans_x = grid->view_min_x; + grid->paint_trans_y = grid->view_min_y - row_offset_h; + grid->paint_start_y = row_offset_h; + grid->paint_cell_item = g_list_nth(grid->cells_tail, + grid->n_cols * grid->row_offset); + + if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE + && grid->state != CLTR_PHOTO_GRID_STATE_LOADING + && grid->state != CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE) + { + float scroll_min_y_offset = (float)(row_offset_h); + + /* Assume zoomed in */ + grid->paint_zoom = grid->zoom_max; + grid->paint_trans_x = grid->view_max_x; + grid->paint_trans_y = grid->view_max_y; + + if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOM_IN) + { + grid->anim_step++; + + /* Are we zoomed all the way in > */ + if (grid->anim_step >= grid->anim_n_steps) + { + grid->state = CLTR_PHOTO_GRID_STATE_ZOOMED; + grid->anim_step = 0; + } + else + { + float f = (float)grid->anim_step/grid->anim_n_steps; + + scroll_min_y_offset *= grid->zoom_max; + + grid->paint_zoom = grid->zoom_min + (zoom_diff * f); + grid->paint_trans_x = view_x_diff * f; + grid->paint_trans_y = (view_y_diff + scroll_min_y_offset) * f; + + grid->paint_start_y = 0; + } + } + else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOM_OUT) + { + grid->anim_step++; + + if (grid->anim_step >= grid->anim_n_steps) + { + grid->paint_zoom = grid->zoom_min; + grid->anim_step = 0; + grid->paint_trans_x = grid->view_min_x; + grid->paint_trans_y = grid->view_min_y - scroll_min_y_offset; + grid->state = CLTR_PHOTO_GRID_STATE_BROWSE; + } + else + { + float f = (float)(grid->anim_n_steps - grid->anim_step ) + / grid->anim_n_steps; + + scroll_min_y_offset *= grid->zoom_max; + + grid->paint_zoom = grid->zoom_min + (zoom_diff * f); + grid->paint_trans_x = view_x_diff * f; + grid->paint_trans_y = (view_y_diff + scroll_min_y_offset) * f; + grid->paint_start_y = 0; + + } + } + else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE) + { + grid->anim_step++; + + if (grid->anim_step >= grid->anim_n_steps) + { + grid->state = CLTR_PHOTO_GRID_STATE_ZOOMED; + grid->anim_step = 0; + } + else + { + float f = (float)grid->anim_step/grid->anim_n_steps; + + grid->paint_trans_x = grid->view_min_x + (view_x_diff * f); + grid->paint_trans_y = grid->view_min_y + (view_y_diff * f); + } + } + else if (grid->state == CLTR_PHOTO_GRID_STATE_SCROLLED_MOVE) + { + grid->paint_zoom = grid->zoom_min; + grid->paint_trans_x = grid->view_min_x; + grid->paint_trans_y = grid->view_min_y - row_offset_h; + grid->anim_step++; + + if (grid->anim_step >= (grid->anim_n_steps/4)) + { + grid->state = CLTR_PHOTO_GRID_STATE_BROWSE; + grid->anim_step = 0; + grid->paint_zoom = grid->zoom_min; + } + else + { + float f = (float)grid->anim_step / (grid->anim_n_steps/4); + + grid->paint_trans_y += (grid->scroll_dist * f); + + if (grid->scroll_dist > 0) /* up */ + { + grid->paint_start_y = (grid->row_offset-1) * grid->cell_height; + } + else /* down */ + { + grid->paint_cell_item = g_list_nth(grid->cells_tail, + grid->n_cols * (grid->row_offset-1)); + } + } + } + } +} + static void cltr_photo_grid_paint(CltrWidget *widget) { int x = 0, y = 0, rows = 0, cols = 0, i =0; GList *cell_item; - float zoom, trans_x, trans_y; - CltrWindow *win = CLTR_WINDOW(widget->parent); + CltrWindow *win = CLTR_WINDOW(widget->parent); CltrPhotoGrid *grid = (CltrPhotoGrid *)widget; rows = grid->n_rows+1; - /* CLTR_MARK();*/ + CLTR_MARK(); glPushMatrix(); - glClear(GL_COLOR_BUFFER_BIT); - if (grid->cells_tail == NULL) { /* No pictures to paint yet */ @@ -503,11 +622,11 @@ cltr_photo_grid_paint(CltrWidget *widget) * see http://blog.metawrap.com/blog/PermaLink.aspx?guid=db82f92e-9fc8-4635-b3e5-e37a1ca6ee0a * for more info * + * Note bg must be glClearColor( 0.0, 0.0, 0.0, 0.0 ) to work. * Is there a better way.? + * - multisample ? */ - glClearColor( 0.0, 0.0, 0.0, 0.0 ); /* needed for saturate to work */ - glEnable(GL_BLEND); glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); /* needed */ @@ -519,127 +638,15 @@ cltr_photo_grid_paint(CltrWidget *widget) glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE); - /* Assume zoomed out */ - zoom = grid->zoom_min; - trans_x = grid->view_min_x; - trans_y = grid->view_min_y - (grid->row_offset * grid->cell_height); + glColor4f(1.0, 1.0, 1.0, 1.0); - y = grid->row_offset * grid->cell_height; + /* values from cltr_photo_grid_update_visual_state() */ - cell_item = g_list_nth(grid->cells_tail, grid->n_cols * grid->row_offset); + cell_item = grid->paint_cell_item; + y = grid->paint_start_y; - if (grid->state != CLTR_PHOTO_GRID_STATE_BROWSE - && grid->state != CLTR_PHOTO_GRID_STATE_LOADING - && grid->state != CLTR_PHOTO_GRID_STATE_LOAD_COMPLETE) - { - float scroll_min_y_offset = (float)(grid->row_offset * grid->cell_height); - /* Assume zoomed in */ - zoom = grid->zoom_max; - trans_x = grid->view_max_x; - trans_y = grid->view_max_y; - - if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOM_IN) - { - grid->anim_step++; - - /* Are we zoomed all the way in > */ - if (grid->anim_step >= grid->anim_n_steps) - { - grid->state = CLTR_PHOTO_GRID_STATE_ZOOMED; - grid->anim_step = 0; - /* zoom = grid->zoom_max; set above */ - } - else - { - float f = (float)grid->anim_step/grid->anim_n_steps; - - scroll_min_y_offset *= grid->zoom_max; - - zoom = grid->zoom_min + ((grid->zoom_max - grid->zoom_min) * f); - trans_x = (grid->view_max_x - grid->view_min_x) * f; - trans_y = (grid->view_max_y - grid->view_min_y + scroll_min_y_offset) * f; - y = 0; - - } - - } - else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOM_OUT) - { - grid->anim_step++; - - if (grid->anim_step >= grid->anim_n_steps) - { - zoom = grid->zoom_min; - grid->anim_step = 0; - trans_x = grid->view_min_x; - trans_y = grid->view_min_y - scroll_min_y_offset; - grid->state = CLTR_PHOTO_GRID_STATE_BROWSE; - } - else - { - float f = (float)(grid->anim_n_steps - grid->anim_step ) - / grid->anim_n_steps; - - zoom = grid->zoom_min + (grid->zoom_max - grid->zoom_min) * f; - scroll_min_y_offset *= grid->zoom_max; - trans_x = (grid->view_max_x - grid->view_min_x) * f; - trans_y = ((grid->view_max_y - grid->view_min_y + scroll_min_y_offset) * f) ; - y = 0; - - } - } - else if (grid->state == CLTR_PHOTO_GRID_STATE_ZOOMED_MOVE) - { - grid->anim_step++; - - if (grid->anim_step >= grid->anim_n_steps) - { - grid->state = CLTR_PHOTO_GRID_STATE_ZOOMED; - grid->anim_step = 0; - } - else - { - float f = (float)grid->anim_step/grid->anim_n_steps; - - trans_x = grid->view_min_x + ((grid->view_max_x - grid->view_min_x) * f); - trans_y = grid->view_min_y + ((grid->view_max_y - grid->view_min_y) * f); - - } - } - else if (grid->state == CLTR_PHOTO_GRID_STATE_SCROLLED_MOVE) - { - zoom = grid->zoom_min; - trans_x = grid->view_min_x; - trans_y = grid->view_min_y - (grid->row_offset * grid->cell_height); - - grid->anim_step++; - - if (grid->anim_step >= (grid->anim_n_steps/4)) - { - grid->state = CLTR_PHOTO_GRID_STATE_BROWSE; - grid->anim_step = 0; - zoom = grid->zoom_min; - } - else - { - float f = (float)grid->anim_step / (grid->anim_n_steps/4); - trans_y += (grid->scroll_dist * f); - - if (grid->scroll_dist > 0) /* up */ - { - y = (grid->row_offset-1) * grid->cell_height; - } - else /* down */ - { - cell_item = g_list_nth(grid->cells_tail, grid->n_cols * (grid->row_offset-1)); - // rows++; - } - } - } - } - - glTranslatef( trans_x, trans_y, 0.0); - glScalef( zoom, zoom, 0.0); + glTranslatef (grid->paint_trans_x, grid->paint_trans_y, 0.0); + glScalef (grid->paint_zoom, grid->paint_zoom, 0.0); while (rows--) { @@ -648,9 +655,9 @@ cltr_photo_grid_paint(CltrWidget *widget) while (cols--) { CltrPhotoGridCell *cell = (CltrPhotoGridCell *)cell_item->data; - Pixbuf *pixb = NULL; - int x1, x2, y1, y2, thumb_w, thumb_h; - int ns_border, ew_border; + Pixbuf *pixb = NULL; + int x1, x2, y1, y2, thumb_w, thumb_h; + int ns_border, ew_border; pixb = cell->pixb; @@ -670,6 +677,11 @@ cltr_photo_grid_paint(CltrWidget *widget) thumb_w = thumb_w + cell->anim_step; thumb_h = thumb_h + cell->anim_step; } + /* set color here for developing effect + * only fully develop when all picts loaded ? + * blur texture too ? + */ + /* glColor4f(1.0, 1.0, 1.0, 0.5); */ cell->anim_step = 0; } @@ -722,8 +734,7 @@ cltr_photo_grid_paint(CltrWidget *widget) glEnable(GL_TEXTURE_2D); - /* back to regular non translated matrix */ - glPopMatrix(); + glPopMatrix(); cell_item = g_list_next(cell_item); @@ -733,6 +744,7 @@ cltr_photo_grid_paint(CltrWidget *widget) x += grid->cell_width; i++; } + y += grid->cell_height; } @@ -741,6 +753,7 @@ cltr_photo_grid_paint(CltrWidget *widget) glPopMatrix(); /* finally paint background */ + glDisable(GL_TEXTURE_2D); glColor3f(0.6, 0.6, 0.62); glRecti(0, 0, widget->width, widget->height); @@ -753,12 +766,28 @@ cltr_photo_grid_paint(CltrWidget *widget) g_mutex_unlock(Mutex_GRID); + /* reset */ + + glDisable(GL_POLYGON_SMOOTH); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); } static void cltr_photo_grid_show(CltrWidget *widget) { - CltrPhotoGrid* grid = CLTR_PHOTO_GRID(widget); + CltrPhotoGrid *grid = CLTR_PHOTO_GRID(widget); + GThread *loader_thread; + + grid->state = CLTR_PHOTO_GRID_STATE_LOADING; + + loader_thread = g_thread_create (cltr_photo_grid_populate, + (gpointer)grid, + TRUE, + NULL); + + g_timeout_add(FPS_TO_TIMEOUT(20), + cltr_photo_grid_idle_cb, grid); cltr_widget_queue_paint(widget); } @@ -771,7 +800,6 @@ cltr_photo_grid_new(int width, const gchar *img_path) { CltrPhotoGrid *grid = NULL; - GThread *loader_thread; grid = g_malloc0(sizeof(CltrPhotoGrid)); @@ -795,6 +823,7 @@ cltr_photo_grid_new(int width, grid->anim_n_steps = 20; /* value needs to be calced dep on rows */ grid->anim_step = 0; + /* Default 'browse view' */ grid->zoom_min = 1.0; grid->view_min_x = (grid->widget.width - (grid->zoom_min * grid->widget.width))/2.0; grid->view_min_y = 0.0; @@ -804,19 +833,7 @@ cltr_photo_grid_new(int width, grid->row_offset = 0; - /* Below needs to go else where - some kind of texture manager/helper */ - Mutex_GRID = g_mutex_new(); - /* Load */ - - loader_thread = g_thread_create (cltr_photo_grid_populate, - (gpointer)grid, - TRUE, - NULL); - - g_timeout_add(FPS_TO_TIMEOUT(20), - cltr_photo_grid_idle_cb, grid); - return CLTR_WIDGET(grid); } diff --git a/cltr-texture.c b/cltr-texture.c index 25bcf5003..6ff32cb5b 100644 --- a/cltr-texture.c +++ b/cltr-texture.c @@ -4,9 +4,7 @@ /* IDEAS or less memory - + up to 4 textures tiled per image *DONE* - - + texture compression ? + + texture compression - made no difference ? + mipmaps - make zoom faster ? ( vs memory ) diff --git a/cltr-widget.c b/cltr-widget.c index 5f1c99726..d0f052c89 100644 --- a/cltr-widget.c +++ b/cltr-widget.c @@ -14,9 +14,10 @@ cltr_widget_new(void) void cltr_widget_show(CltrWidget *widget) { + widget->visible = TRUE; + if (widget->show) { - widget->visible = TRUE; widget->show(widget); } } @@ -60,8 +61,27 @@ cltr_widget_hide(CltrWidget *widget) void cltr_widget_paint(CltrWidget *widget) { - if (widget->paint && widget->visible) - widget->paint(widget); + if (widget->visible) + { + GList *child_item = widget->children;; + + if (widget->paint) + widget->paint(widget); + + /* Recurse down */ + if (child_item) + { + do + { + CltrWidget *child = CLTR_WIDGET(child_item->data); + + if (child->visible) + cltr_widget_paint(child); + + } + while ((child_item = g_list_next(child_item)) != NULL); + } + } } void diff --git a/cltr-window.c b/cltr-window.c index 337c5797a..73999d8dd 100644 --- a/cltr-window.c +++ b/cltr-window.c @@ -7,6 +7,9 @@ cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev); static void cltr_window_show(CltrWidget *widget); +static void +cltr_window_paint(CltrWidget *widget); + struct CltrWindow { CltrWidget widget; @@ -25,6 +28,7 @@ cltr_window_new(int width, int height) win->widget.width = width; win->widget.height = height; win->widget.show = cltr_window_show; + win->widget.paint = cltr_window_paint; win->widget.xevent_handler = cltr_window_handle_xevent; win->xwin = XCreateSimpleWindow(CltrCntx.xdpy, @@ -55,12 +59,6 @@ cltr_window_new(int width, int height) return CLTR_WIDGET(win); } -Window -cltr_window_xwin(CltrWindow *win) -{ - return win->xwin; -} - static void cltr_window_show(CltrWidget *widget) { @@ -70,12 +68,21 @@ cltr_window_show(CltrWidget *widget) /* XXX set focused call */ if (widget->children) { - win->focused_child = g_list_nth_data(widget->children, 0); + if (win->focused_child == NULL) + win->focused_child = g_list_nth_data(widget->children, 0); } XMapWindow(ctx->xdpy, win->xwin); } +static void +cltr_window_paint(CltrWidget *widget) +{ + glClear(GL_COLOR_BUFFER_BIT); + glClearColor( 0.0, 0.0, 0.0, 0.0 ); /* needed for saturate to work */ + +} + static gboolean cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev) { @@ -85,7 +92,7 @@ cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev) if (xev->type == Expose) { - ; + cltr_widget_queue_paint(widget); } /* XXX Very basic - assumes we are only interested in mouse clicks */ @@ -95,7 +102,22 @@ cltr_window_handle_xevent (CltrWidget *widget, XEvent *xev) return FALSE; } -/* window only */ - +/* window only methods */ + +Window +cltr_window_xwin(CltrWindow *win) +{ + return win->xwin; +} + +Window +cltr_window_focus_widget(CltrWindow *win, CltrWidget *widget) +{ + /* XXX Should check widget is an actual child of the window */ + + ClutterMainContext *ctx = CLTR_CONTEXT(); + + win->focused_child = widget; +} diff --git a/cltr-window.h b/cltr-window.h index 237bec79b..e5baae0f2 100644 --- a/cltr-window.h +++ b/cltr-window.h @@ -10,14 +10,19 @@ typedef struct CltrWindow CltrWindow; CltrWidget* cltr_window_new(int width, int height); -Window -cltr_window_xwin(CltrWindow *win); - void cltr_window_paint(CltrWidget *widget); void cltr_window_add_widget(CltrWindow *win, CltrWidget *widget, int x, int y); +/* win only methods */ + +Window +cltr_window_xwin(CltrWindow *win); + +Window +cltr_window_focus_widget(CltrWindow *win, CltrWidget *widget); + #endif diff --git a/cltr.c b/cltr.c index addfdd27f..de2950911 100644 --- a/cltr.c +++ b/cltr.c @@ -3,7 +3,8 @@ int main(int argc, char **argv) { - CltrWidget *win = NULL, *grid = NULL; + CltrWidget *win = NULL, *grid = NULL, *test = NULL, *test2 = NULL; + CltrWidget *list; if (argc < 2) { @@ -16,10 +17,25 @@ main(int argc, char **argv) win = cltr_window_new(640, 480); - grid = cltr_photo_grid_new(640, 480, 3, 3, argv[1]); + /* + grid = cltr_photo_grid_new(640, 480, 4, 4, argv[1]); + + test = cltr_scratch_new(100, 100); + test2 = cltr_scratch_new(150, 150); cltr_widget_add_child(win, grid, 0, 0); + + cltr_widget_add_child(win, test, 320, 240); + cltr_widget_add_child(win, test2, 400, 300); + + cltr_window_focus_widget(CLTR_WINDOW(win), grid); + */ + + list = cltr_list_new(640,480,640, 160); + + cltr_widget_add_child(win, list, 0, 0); + cltr_widget_show_all(win); cltr_main_loop(); diff --git a/cltr.h b/cltr.h index d7029e3c4..18695ae08 100644 --- a/cltr.h +++ b/cltr.h @@ -27,6 +27,17 @@ typedef enum CltrDirection } CltrDirection; +typedef struct CltrRect +{ + int x, y, width, height; +} +CltrRect; + +#define cltr_rect_x1(r) ((r).x) +#define cltr_rect_y1(r) ((r).y) +#define cltr_rect_x2(r) ((r).x + (r).width) +#define cltr_rect_y2(r) ((r).y + (r).height) + /* texture stuff */ /* ******************* */ diff --git a/pixbuf.c b/pixbuf.c index 31895296a..a8337beb2 100644 --- a/pixbuf.c +++ b/pixbuf.c @@ -577,6 +577,24 @@ pixbuf_copy(Pixbuf *src_pixb, } } +void +pixbuf_fill_rect(Pixbuf *pixb, + int x, + int y, + int width, + int height, + PixbufPixel *p) +{ + int i, j; + + if (width < 0) width = pixb->width; + if (height < 0) height = pixb->height; + + for (i = x; i