Hi

To better get to know the plotters API I started working on a plotters
based select widget. This patch replaces the pop-up menu with a list
displayed right under the gadget. I am sending it mainly to listen to
what you think of the direction taken so if you have any comments on
the appearance of the gadget or any necessary features, I think it
would be best to know at the initial steps of creating it :). I
consider it a draft and I know the code could be better organised and
less messy so please be understanding at the moment :). My current
todo list contains:

- adding an arrow to the box so that it resembles  a combo box
- making the colours customizable
- adding a scroll for really long lists(I'll use the existing one)
- adding a representation of optgroup
- a better handling of mouse events(now it responds only to a click
without the slightest mouse move)
Index: render/form.c
===================================================================
--- render/form.c	(wersja 7073)
+++ render/form.c	(kopia robocza)
@@ -29,6 +29,10 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
+#include "css/css.h"
+#include "desktop/browser.h"
+#include "desktop/plotters.h"
+#include "desktop/knockout.h"
 #include "render/box.h"
 #include "render/form.h"
 #include "utils/log.h"
@@ -41,6 +45,7 @@
 static char *form_acceptable_charset(struct form *form);
 static char *form_encode_item(const char *item, const char *charset,
 		const char *fallback);
+static bool form_redraw_select_menu(struct browser_window *bw, int first_option);		
 
 /**
  * Create a struct form.
@@ -812,3 +817,151 @@
 	return ret;
 }
 
+bool form_show_select_menu(struct browser_window *bw,
+		struct form_control *control)
+{
+	if (visible_select_menu)
+		return false;
+	
+	visible_select_menu = control;
+	form_redraw_select_menu(bw, 1);
+	return true;
+}
+
+bool form_hide_select_menu(struct browser_window *bw)
+{
+	struct box *box;	
+	int x, y, width, height;	
+	
+	if (!visible_select_menu)
+		return false;
+	
+	box = visible_select_menu->box;
+	box_coords(box, &x, &y);
+	
+	x -= box->border[3];
+	y += box->height + box->border[2] + box->padding[2] + box->padding[0];	
+	
+	width = box->width + box->border[1] + box->border[3] + box->padding[1]
+			+ box->padding[3];	
+	height = visible_select_menu->data.select.height;
+	
+	x *= bw->scale;
+	y *= bw->scale;
+	width *= bw->scale;
+	height *= bw->scale;
+	
+	browser_window_redraw_rect(bw, x, y, width + 1, height + 1);
+	visible_select_menu = NULL;	
+	return true;
+}
+
+bool form_redraw_select_menu(struct browser_window *bw, int first_option)
+{
+	struct box *box;
+	struct form_option *option;
+	bool result, want_knockout;
+	int x, y, width, height, line_height;
+	int x0, y0, x1, y1;
+	int num_lines, i;
+	int colour;
+	float scale = bw->scale;
+		
+	if (!visible_select_menu)
+		return false;
+		
+	box = visible_select_menu->box;
+	box_coords(box, &x, &y);
+	
+	x -= box->border[3];
+	y += box->height + box->border[2] + box->padding[2] + box->padding[0];
+	
+	width = box->width + box->border[1] + box->border[3] + box->padding[1]
+			+ box->padding[3];
+	
+	line_height = css_len2px(&(box->style->font_size.value.length),
+			box->style);
+	
+	if (visible_select_menu->data.select.num_items < 20)
+		num_lines = visible_select_menu->data.select.num_items;
+	else
+		num_lines = 20;
+	
+	height = visible_select_menu->data.select.height = num_lines
+			* (line_height + 5);
+					
+	want_knockout = plot.option_knockout;
+	if (want_knockout)
+		knockout_plot_start(&plot);
+
+	x0 = x * scale;
+	y0 = y * scale;
+	x1 = (x + width) * scale;
+	y1 = (y + height) * scale;
+	
+	result = plot.clip(x0, y0, x1, y1);
+	result &= plot.clg(0xDDDDDD);
+	
+	option = visible_select_menu->data.select.items;
+	i = 0;
+	while (option && i < num_lines) {
+		
+		
+		y0 = (y + i * (line_height + 5)) * scale;
+		y1 = (y + (i + 1) * (line_height + 5)) * scale;
+		
+		plot.clip(x0, y0, x1, y1);		
+		if (option->selected) {
+			colour = 0xDB9370;
+			plot.clg(colour);
+		}
+		else
+			colour = 0xDDDDDD;
+		
+		y0 = y + i * (line_height + 5) + (int) (line_height * 0.75) + 5;
+		y0 *= scale;
+		plot.text((x + box->border[3] + box->padding[3]) * scale, y0,
+			  	box->style, option->text, strlen(option->text),
+    				colour, 0x000000);
+		
+		i++;
+		option = option->next;
+	}
+	
+	y0 = y * scale;
+	y1 = (y + height) * scale;
+	plot.clip(x0, y0, x1, y1);	
+	plot.rectangle(x0, y0, width * scale, height * scale, 1, 0x000000,
+			false, false);
+		
+	if (want_knockout)
+		knockout_plot_end();
+
+	return result;
+}
+
+void form_select_menu_clicked(struct browser_window *bw,
+		struct form_control *control, int x, int y)
+{
+	struct box *box;
+	struct form_option *option;	
+	int line_height;	
+	int i;
+	
+	box = visible_select_menu->box;
+	
+	line_height = css_len2px(&(box->style->font_size.value.length),
+				   box->style);
+	option = visible_select_menu->data.select.items;
+	i = 0;
+	while (option && y > (line_height + 5)) {
+		y -= line_height + 5;
+		i++;
+		option = option->next;
+	}
+	
+	if (option)
+		browser_window_form_select(bw, visible_select_menu, i);
+	
+	form_redraw_select_menu(bw, 1);
+}
Index: render/form.h
===================================================================
--- render/form.h	(wersja 7073)
+++ render/form.h	(kopia robocza)
@@ -31,6 +31,8 @@
 struct form_control;
 struct form_option;
 
+struct form_control *visible_select_menu;
+
 /** Form submit method. */
 typedef enum {
 	method_GET,		/**< GET, always url encoded. */
@@ -105,6 +107,7 @@
 			int num_selected;
 			/** Currently selected item, if num_selected == 1. */
 			struct form_option *current;
+			int height;
 		} select;
 	} data;
 
@@ -144,5 +147,7 @@
 char *form_url_encode(struct form *form,
 		struct form_successful_control *control);
 void form_free_successful(struct form_successful_control *control);
-
+bool form_show_select_menu(struct browser_window *bw, struct form_control *control);
+bool form_hide_select_menu(struct browser_window *bw);
+void form_select_menu_clicked(struct browser_window *bw, struct form_control *control, int x, int y);
 #endif
Index: gtk/gtk_window.c
===================================================================
--- gtk/gtk_window.c	(wersja 7073)
+++ gtk/gtk_window.c	(kopia robocza)
@@ -411,6 +411,19 @@
 	bool shift = event->state & GDK_SHIFT_MASK;
 	bool ctrl = event->state & GDK_CONTROL_MASK;
 
+	current_widget = widget;
+	current_drawable = widget->window;
+	current_gc = gdk_gc_new(current_drawable);
+#ifdef CAIRO_VERSION
+	current_cr = gdk_cairo_create(current_drawable);
+#endif
+
+	plot = nsgtk_plotters;
+	nsgtk_plot_set_scale(g->bw->scale);
+	current_redraw_browser = g->bw;	
+		
+	
+	
 	/* If the mouse state is PRESS then we are waiting for a release to emit
 	 * a click event, otherwise just reset the state to nothing*/
 	if (g->mouse->state & BROWSER_MOUSE_PRESS_1)
@@ -430,6 +443,16 @@
 	else
 		browser_window_mouse_drag_end(g->bw, 0, event->x, event->y);
 
+	
+	current_redraw_browser = NULL;
+
+	g_object_unref(current_gc);
+#ifdef CAIRO_VERSION
+	cairo_destroy(current_cr);
+#endif	
+	
+	
+	
 	g->mouse->state = 0;
 	return TRUE;
 }
Index: desktop/browser.c
===================================================================
--- desktop/browser.c	(wersja 7073)
+++ desktop/browser.c	(kopia robocza)
@@ -1409,6 +1409,31 @@
 	bw->drag_type = DRAGGING_NONE;
 	bw->scrolling_box = NULL;
 
+	
+	if (visible_select_menu != NULL) {
+		int x0, y0, x1, y1;
+		box = visible_select_menu->box;
+		box_coords(box, &box_x, &box_y);
+		x0 = box_x - box->border[3];
+		y0 = box_y + box->height + box->border[2] + box->padding[2]
+				+ box->padding[0];
+		x1 = box_x + box->width + box->border[1] + box->border[3]
+				+ box->padding[1] + box->padding[3];
+		y1 = y0 + visible_select_menu->data.select.height;
+		
+		if (x > x0 && x < x1 && y >  y0 && y < y1
+				&& mouse & BROWSER_MOUSE_CLICK_1) {
+			
+			form_select_menu_clicked(bw, visible_select_menu,
+					x - x0,
+					y - y0);
+		}
+		else if (mouse & BROWSER_MOUSE_CLICK_1)
+			form_hide_select_menu(bw);
+		
+		return;
+	}
+	
 	/* search the box tree for a link, imagemap, form control, or
 	 * box with scrollbars */
 
@@ -1499,7 +1524,8 @@
 			status = messages_get("FormSelect");
 			pointer = GUI_POINTER_MENU;
 			if (mouse & BROWSER_MOUSE_CLICK_1)
-				gui_create_form_select_menu(bw, gadget);
+				//gui_create_form_select_menu(bw, gadget);
+				form_show_select_menu(bw, gadget);
 			break;
 		case GADGET_CHECKBOX:
 			status = messages_get("FormCheckbox");

Reply via email to