2 * item-edit.c : Edit facilities for worksheets.
4 * (C) 1999-2004 Miguel de Icaza & Jody Goldberg
6 * This module provides:
7 * * Integration of an in-sheet text editor (GtkEntry) with the Workbook
8 * GtkEntry as a canvas item.
10 * * Feedback on expressions in the spreadsheet (referenced cells or
11 * ranges are highlighted on the spreadsheet).
13 #include <gnumeric-config.h>
16 #include <item-edit.h>
17 #include <gnm-pane-impl.h>
19 #include <item-cursor.h>
20 #include <sheet-control-gui-priv.h>
22 #include <sheet-view.h>
23 #include <sheet-style.h>
24 #include <sheet-merge.h>
28 #include <style-font.h>
29 #include <style-color.h>
31 #include <parse-util.h>
35 #include <widgets/gnumeric-expr-entry.h>
36 #define GNUMERIC_ITEM "EDIT"
38 #include <gsf/gsf-impl-utils.h>
40 #include <goffice/goffice.h>
42 static GocItemClass
*parent_class
;
48 GtkEntry
*entry
; /* Utility pointer to the workbook entry */
54 gboolean cursor_visible
;
62 typedef GocItemClass GnmItemEditClass
;
64 /* The arguments we take */
67 ARG_SHEET_CONTROL_GUI
/* The SheetControlGUI * argument */
71 get_top_left (GnmItemEdit
const *ie
, int *top
, int *left
, PangoDirection dir
)
73 GnmVAlign
const align
= gnm_style_get_align_v (ie
->style
);
74 GocItem
*item
= GOC_ITEM (ie
);
75 GocCanvas
*canvas
= item
->canvas
;
76 double l
= ((goc_canvas_get_direction (canvas
) == GOC_DIRECTION_LTR
&& dir
== PANGO_DIRECTION_RTL
)
77 || (goc_canvas_get_direction (canvas
) == GOC_DIRECTION_RTL
&& dir
!= PANGO_DIRECTION_RTL
))?
78 item
->x1
- 1: item
->x0
;
80 goc_canvas_c2w (canvas
, l
, item
->y0
, left
, top
);
82 if (align
== GNM_VALIGN_CENTER
|| align
== GNM_VALIGN_DISTRIBUTED
||
83 align
== GNM_VALIGN_BOTTOM
) {
84 int text_height
, height
= (int)(ie
->item
.y1
- ie
->item
.y0
) * canvas
->pixels_per_unit
;
85 pango_layout_get_pixel_size (ie
->layout
, NULL
, &text_height
);
86 *top
+= (align
!= GNM_VALIGN_BOTTOM
)
87 ? (height
- text_height
)/2
88 : (height
- text_height
);
93 gnm_apply_attribute_list_cb (PangoAttribute
*attribute
,
96 PangoAttrList
*attrs
= data
;
97 if (attribute
->klass
->type
== PANGO_ATTR_FOREGROUND
) {
98 PangoAttribute
*copy
= pango_attribute_copy (attribute
);
99 pango_attr_list_change (attrs
, copy
);
105 gnm_apply_attribute_list (PangoAttrList
*attrs
, PangoAttrList
*added_attrs
)
107 if (added_attrs
== NULL
)
109 pango_attr_list_unref (pango_attr_list_filter (added_attrs
,
110 gnm_apply_attribute_list_cb
,
115 item_edit_draw (GocItem
const *item
, cairo_t
*cr
)
117 GnmItemEdit
const *ie
= GNM_ITEM_EDIT (item
);
118 GtkStyleContext
*context
= goc_item_get_style_context (item
);
121 int x0
, y0
, x1
, y1
; /* in widget coordinates */
123 PangoRectangle pos
, weak
;
124 char const *text
= gtk_entry_get_text (ie
->entry
);
126 PangoDirection dir
= pango_find_base_dir (text
, -1);
127 PangoAttrList
*entry_attributes
128 = g_object_get_data(G_OBJECT (ie
->entry
),
129 "gnm:range-attributes");
131 if (entry_attributes
!= NULL
) {
132 if (go_pango_attr_list_is_empty (entry_attributes
))
133 entry_attributes
= NULL
;
135 entry_attributes
= pango_attr_list_ref (entry_attributes
);
138 get_top_left (ie
, &top
, &left
, dir
);
139 if (goc_canvas_get_direction (item
->canvas
) == GOC_DIRECTION_RTL
) {
140 goc_canvas_c2w (item
->canvas
, item
->x1
, item
->y0
, &x0
, &y0
);
141 goc_canvas_c2w (item
->canvas
, item
->x0
, item
->y1
, &x1
, &y1
);
143 goc_canvas_c2w (item
->canvas
, item
->x0
, item
->y0
, &x0
, &y0
);
144 goc_canvas_c2w (item
->canvas
, item
->x1
, item
->y1
, &x1
, &y1
);
149 cairo_rectangle (cr
, x0
, y0
, x1
- x0
, y1
- y0
);
150 /* avoid a weak/strong cursor to extend outside the item,
151 a better fix would be to have enough room for cursors */
153 if (gnm_pattern_background_set (ie
->style
, cr
, FALSE
, NULL
)) {
154 cairo_rectangle (cr
, x0
, y0
, x1
- x0
, y1
- y0
);
157 gtk_render_background (context
, cr
, x0
, y0
, x1
- x0
, y1
- y0
);
160 /* set the default color */
161 gnm_style_context_get_color (context
, GTK_STATE_FLAG_NORMAL
, &fcolor
);
162 gdk_cairo_set_source_rgba (cr
, &fcolor
);
163 color
= go_color_from_gdk_rgba (&fcolor
, NULL
);
165 if (dir
== PANGO_DIRECTION_RTL
) {
166 pango_layout_get_pixel_extents (ie
->layout
, NULL
, &pos
);
167 left
-= pos
.width
+ GNM_COL_MARGIN
/ goc_canvas_get_pixels_per_unit (item
->canvas
);
169 cairo_move_to (cr
, left
, top
);
170 gtk_editable_get_selection_bounds (GTK_EDITABLE (ie
->entry
), &start
, &end
);
172 PangoAttribute
*attr
;
173 PangoAttrList
*orig
= pango_attr_list_ref (pango_layout_get_attributes (ie
->layout
)),
174 *attrs
= pango_attr_list_copy (orig
);
175 start
= g_utf8_offset_to_pointer (text
, start
) - text
;
176 end
= g_utf8_offset_to_pointer (text
, end
) - text
;
177 color
= gnm_style_get_back_color (ie
->style
)->go_color
;
178 attr
= go_color_to_pango (color
, FALSE
);
179 attr
->start_index
= start
;
180 attr
->end_index
= end
;
181 pango_attr_list_change (attrs
, attr
);
182 color
= gnm_style_get_font_color (ie
->style
)->go_color
;
183 attr
= go_color_to_pango (color
, TRUE
);
184 attr
->start_index
= start
;
185 attr
->end_index
= end
;
186 pango_attr_list_change (attrs
, attr
);
187 gnm_apply_attribute_list (attrs
, entry_attributes
);
188 pango_layout_set_attributes (ie
->layout
, attrs
);
189 pango_attr_list_unref (attrs
);
190 pango_cairo_show_layout (cr
, ie
->layout
);
191 pango_layout_set_attributes (ie
->layout
, orig
);
192 pango_attr_list_unref (orig
);
193 } else if (entry_attributes
!= NULL
) {
194 PangoAttrList
*orig
= pango_attr_list_ref (pango_layout_get_attributes (ie
->layout
)),
195 *attrs
= pango_attr_list_copy (orig
);
196 gnm_apply_attribute_list (attrs
, entry_attributes
);
197 pango_layout_set_attributes (ie
->layout
, attrs
);
198 pango_attr_list_unref (attrs
);
199 pango_cairo_show_layout (cr
, ie
->layout
);
200 pango_layout_set_attributes (ie
->layout
, orig
);
201 pango_attr_list_unref (orig
);
203 pango_cairo_show_layout (cr
, ie
->layout
);
205 pango_attr_list_unref (entry_attributes
);
207 if (ie
->cursor_visible
) {
208 int cursor_pos
= gtk_editable_get_position (GTK_EDITABLE (ie
->entry
));
209 double incr
= (dir
== PANGO_DIRECTION_RTL
)? -.5: .5, x
, ytop
, ybottom
;
210 pango_layout_get_cursor_pos (ie
->layout
,
211 g_utf8_offset_to_pointer (text
, cursor_pos
) - text
, &pos
, &weak
);
212 cairo_set_line_width (cr
, 1.);
213 cairo_set_dash (cr
, NULL
, 0, 0.);
214 cairo_set_line_cap (cr
, CAIRO_LINE_CAP_BUTT
);
215 cairo_set_line_join (cr
, CAIRO_LINE_JOIN_MITER
);
216 cairo_set_source_rgba (cr
, GO_COLOR_TO_CAIRO (gnm_style_get_back_color (ie
->style
)->go_color
^ 0xffffff00));
217 x
= left
+ PANGO_PIXELS (pos
.x
) + incr
;
218 ytop
= top
+ PANGO_PIXELS (pos
.y
);
219 ybottom
= top
+ PANGO_PIXELS (pos
.y
+ pos
.height
) - 1;
220 cairo_move_to (cr
, x
, ytop
);
221 cairo_line_to (cr
, x
, ybottom
);
223 if (weak
.x
!= pos
.x
) {
224 double w
= (ybottom
- ytop
) / 4.;
225 GOColor color1
= color
^ 0xffffff00;
227 cairo_move_to (cr
, x
, ybottom
);
228 cairo_line_to (cr
, x
+ w
* incr
, ybottom
- w
/ 2.);
229 cairo_line_to (cr
, x
, ybottom
- w
);
230 cairo_close_path (cr
);
232 color
= GO_COLOR_INTERPOLATE (color
, color1
, 0.5);
233 x
= left
+ PANGO_PIXELS (weak
.x
) - incr
;
234 ytop
= top
+ PANGO_PIXELS (weak
.y
);
235 ybottom
= top
+ PANGO_PIXELS (weak
.y
+ weak
.height
) - 1;
236 cairo_set_source_rgba (cr
, GO_COLOR_TO_CAIRO (color
));
237 cairo_move_to (cr
, x
, ytop
);
238 cairo_line_to (cr
, x
, ybottom
);
241 cairo_move_to (cr
, x
, ybottom
);
242 cairo_line_to (cr
, x
- w
* incr
, ybottom
- w
/ 2.);
243 cairo_line_to (cr
, x
, ybottom
- w
);
244 cairo_close_path (cr
);
252 item_edit_distance (GocItem
*item
, double cx
, double cy
,
253 GocItem
**actual_item
)
256 if ((cx
< item
->x0
) || (cy
< item
->y0
) || (cx
>= item
->x1
) || (cy
>= item
->y1
))
264 item_edit_enter_notify (GocItem
*item
, G_GNUC_UNUSED
double x
, G_GNUC_UNUSED
double y
)
266 gnm_widget_set_cursor_type (GTK_WIDGET (item
->canvas
), GDK_XTERM
);
271 item_edit_button_pressed (GocItem
*item
, int button
, double x
, double y
)
274 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
275 GtkEditable
*ed
= GTK_EDITABLE (ie
->entry
);
276 int target_index
, trailing
;
277 char const *text
= pango_layout_get_text (ie
->layout
);
278 PangoDirection dir
= pango_find_base_dir (text
, -1);
280 GocDirection cdir
= goc_canvas_get_direction (item
->canvas
);
282 if (cdir
== GOC_DIRECTION_RTL
)
283 x
= item
->x1
- x
- 1;
287 if (dir
== PANGO_DIRECTION_RTL
) {
288 pango_layout_get_pixel_extents (ie
->layout
, NULL
, &pos
);
289 x
-= item
->x1
- item
->x0
- (pos
.width
290 + 2 * GNM_COL_MARGIN
) / goc_canvas_get_pixels_per_unit (item
->canvas
);
292 /* the layout might be zoomed, we need to adjust x and y accordingly */
293 x
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
294 y
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
296 if (pango_layout_xy_to_index (ie
->layout
,
297 x
* PANGO_SCALE
, y
* PANGO_SCALE
,
298 &target_index
, &trailing
)) {
299 int preedit
= GNM_PANE (item
->canvas
)->preedit_length
;
300 gint cur_index
= gtk_editable_get_position (ed
);
301 cur_index
= g_utf8_offset_to_pointer (text
, cur_index
) - text
;
303 if (target_index
>= cur_index
&& preedit
> 0) {
304 if (target_index
< (cur_index
+ preedit
)) {
305 target_index
= cur_index
;
308 target_index
-= preedit
;
311 /* the click occured after text end (#388342) */
312 target_index
= strlen (text
);
315 ie
->sel_start
= g_utf8_pointer_to_offset (text
, text
+ target_index
) + trailing
;
316 gtk_editable_set_position (GTK_EDITABLE (ie
->entry
), ie
->sel_start
);
325 item_edit_motion (GocItem
*item
, double x
, double y
)
327 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
328 if (ie
->sel_start
>= 0) {
329 GtkEditable
*ed
= GTK_EDITABLE (ie
->entry
);
330 int target_index
, trailing
;
331 char const *text
= pango_layout_get_text (ie
->layout
);
332 PangoDirection dir
= pango_find_base_dir (text
, -1);
334 GocDirection cdir
= goc_canvas_get_direction (item
->canvas
);
336 if (cdir
== GOC_DIRECTION_RTL
)
337 x
= item
->x1
- x
- 1;
341 if (dir
== PANGO_DIRECTION_RTL
) {
342 pango_layout_get_pixel_extents (ie
->layout
, NULL
, &pos
);
343 x
-= item
->x1
- item
->x0
- (pos
.width
344 + 2 * GNM_COL_MARGIN
) / goc_canvas_get_pixels_per_unit (item
->canvas
);
346 /* the layout might be zoomed, we need to adjust x and y accordingly */
347 x
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
348 y
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
350 if (pango_layout_xy_to_index (ie
->layout
,
351 x
* PANGO_SCALE
, y
* PANGO_SCALE
,
352 &target_index
, &trailing
)) {
353 int preedit
= GNM_PANE (item
->canvas
)->preedit_length
;
354 gint cur_index
= gtk_editable_get_position (ed
);
355 cur_index
= g_utf8_offset_to_pointer (text
, cur_index
) - text
;
357 if (target_index
>= cur_index
&& preedit
> 0) {
358 if (target_index
< (cur_index
+ preedit
)) {
359 target_index
= cur_index
;
362 target_index
-= preedit
;
365 /* the click occured after text end (#388342) */
366 target_index
= strlen (text
);
369 target_index
= g_utf8_pointer_to_offset (text
, text
+ target_index
) + trailing
;
370 if (target_index
> ie
->sel_start
)
371 gtk_editable_select_region (GTK_EDITABLE (ie
->entry
), ie
->sel_start
, target_index
);
373 gtk_editable_select_region (GTK_EDITABLE (ie
->entry
), target_index
, ie
->sel_start
);
374 goc_item_invalidate (item
);
382 item_edit_button_released (GocItem
*item
, G_GNUC_UNUSED
int button
,
383 G_GNUC_UNUSED
double x
, G_GNUC_UNUSED
double y
)
385 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
386 if (ie
->sel_start
>= 0) {
394 item_edit_update_bounds (GocItem
*item
)
396 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
397 double scale
= item
->canvas
->pixels_per_unit
;
399 if (ie
->gfont
!= NULL
) {
400 GtkWidget
const *canvas
= GTK_WIDGET (item
->canvas
);
401 GnmPane
const *pane
= GNM_PANE (item
->canvas
);
402 ColRowInfo
const *ci
;
403 Sheet
const *sheet
= scg_sheet (ie
->scg
);
404 GnmFont
const *gfont
= ie
->gfont
;
405 GnmRange
const *merged
;
406 int col
, tmp
, width
, height
, col_size
;
407 char const *text
, *entered_text
;
408 PangoAttrList
*attrs
;
409 PangoAttribute
*attr
;
410 int cursor_pos
= gtk_editable_get_position (GTK_EDITABLE (ie
->entry
));
412 GocDirection cdir
= goc_canvas_get_direction (item
->canvas
);
414 entered_text
= gtk_entry_get_text (ie
->entry
);
415 text
= wbcg_edit_get_display_text (scg_wbcg (ie
->scg
));
416 pango_layout_set_text (ie
->layout
, text
, -1);
417 dir
= pango_find_base_dir (text
, -1);
419 pango_layout_set_font_description (ie
->layout
, gfont
->go
.font
->desc
);
420 pango_layout_set_wrap (ie
->layout
, PANGO_WRAP_WORD_CHAR
);
421 pango_layout_set_width (ie
->layout
, (int)(item
->x1
- item
->x0
)*PANGO_SCALE
);
423 attrs
= wbcg_edit_get_markup (scg_wbcg (ie
->scg
), TRUE
);
425 attrs
= pango_attr_list_copy (attrs
);
427 attrs
= gnm_style_generate_attrs_full (ie
->style
);
429 /* reverse video the auto completion text */
430 if (entered_text
!= NULL
&& entered_text
!= text
) {
431 int const start
= strlen (entered_text
);
432 GnmColor
const *color
= gnm_style_get_font_color (ie
->style
);
433 attr
= go_color_to_pango (color
->go_color
, FALSE
);
434 attr
->start_index
= start
;
435 attr
->end_index
= G_MAXINT
;
436 pango_attr_list_insert (attrs
, attr
);
438 color
= gnm_style_get_back_color (ie
->style
);
439 attr
= go_color_to_pango (color
->go_color
, TRUE
);
440 attr
->start_index
= start
;
441 attr
->end_index
= G_MAXINT
;
442 pango_attr_list_insert (attrs
, attr
);
444 pango_attr_list_insert_before (attrs
,
445 pango_attr_scale_new (scale
));
447 pango_layout_set_attributes (ie
->layout
, attrs
);
448 pango_attr_list_unref (attrs
);
450 go_pango_translate_layout (ie
->layout
);
452 if (pane
->preedit_length
) {
453 PangoAttrList
*tmp_attrs
= pango_attr_list_new ();
454 pango_attr_list_splice (tmp_attrs
, pane
->preedit_attrs
,
455 g_utf8_offset_to_pointer (text
, cursor_pos
) - text
,
456 g_utf8_offset_to_pointer (text
, cursor_pos
+ pane
->preedit_length
) - text
);
457 pango_layout_set_attributes (ie
->layout
, tmp_attrs
);
458 pango_attr_list_unref (tmp_attrs
);
461 pango_layout_set_width (ie
->layout
, -1);
462 pango_layout_get_pixel_size (ie
->layout
, &width
, &height
);
465 if (NULL
== (merged
= gnm_sheet_merge_is_corner (sheet
, &ie
->pos
))) {
466 ci
= sheet_col_get_info (sheet
, col
);
467 g_return_if_fail (ci
!= NULL
);
468 col_size
= ci
->size_pixels
;
470 col_size
= scg_colrow_distance_get (ie
->scg
, TRUE
,
471 merged
->start
.col
, merged
->end
.col
+1);
473 /* both margins and the gridline */
474 col_size
-= GNM_COL_MARGIN
+ GNM_COL_MARGIN
+ 1;
476 /* far corner based on the span size
477 * - margin on each end
478 * - the bound excludes the far point => +1 */
480 col
= merged
->end
.col
;
482 if ((dir
== PANGO_DIRECTION_RTL
&& cdir
== GOC_DIRECTION_RTL
) ||
483 (dir
!= PANGO_DIRECTION_RTL
&& cdir
== GOC_DIRECTION_LTR
)) {
486 while (col_size
< width
&&
487 col
<= pane
->last_full
.col
&&
488 col
< gnm_sheet_get_last_col (sheet
)) {
489 ci
= sheet_col_get_info (sheet
, ++col
);
491 g_return_if_fail (ci
!= NULL
);
494 col_size
+= ci
->size_pixels
;
496 gtk_widget_get_allocation (GTK_WIDGET (canvas
), &a
);
497 tmp
= (pane
->first_offset
.x
+ a
.width
) / scale
;
498 item
->x1
= item
->x0
+ (col_size
+ GNM_COL_MARGIN
+ GNM_COL_MARGIN
+ 1) / scale
;
500 if (item
->x1
>= tmp
) {
502 pango_layout_set_width (ie
->layout
, (item
->x1
- item
->x0
+ 1)*PANGO_SCALE
);
503 pango_layout_get_pixel_size (ie
->layout
, &width
, &height
);
506 item
->x1
= (1 + pane
->first_offset
.x
+
507 scg_colrow_distance_get (ie
->scg
, TRUE
,
509 ie
->pos
.col
+1)) / scale
;
510 while (col_size
< width
&&
511 col
> pane
->first
.col
&&
513 ci
= sheet_col_get_info (sheet
, --col
);
515 g_return_if_fail (ci
!= NULL
);
518 col_size
+= ci
->size_pixels
;
520 if (col_size
< width
)
522 tmp
= pane
->first_offset
.x
/ scale
;
523 item
->x0
= item
->x1
- (col_size
+ GNM_COL_MARGIN
+ GNM_COL_MARGIN
+ 1) / scale
;
524 if (item
->x0
<= tmp
) {
526 pango_layout_set_width (ie
->layout
, (item
->x1
- item
->x0
+ 1)*PANGO_SCALE
);
527 pango_layout_get_pixel_size (ie
->layout
, &width
, &height
);
531 tmp
= scg_colrow_distance_get (ie
->scg
, FALSE
, ie
->pos
.row
,
532 (merged
? merged
->end
.row
: ie
->pos
.row
) + 1) - 1;
533 item
->y1
= item
->y0
+ (MAX (height
, tmp
)) / scale
;
538 cb_entry_key_press (GocItem
*item
)
540 goc_item_bounds_changed (item
);
545 cb_entry_cursor_event (GocItem
*item
)
547 /* ensure we draw a cursor when moving quickly no matter what the
548 * current state is */
549 GNM_ITEM_EDIT (item
)->cursor_visible
= TRUE
;
550 goc_item_invalidate (item
);
556 cb_item_edit_cursor_blink (GnmItemEdit
*ie
)
558 GocItem
*item
= GOC_ITEM (ie
);
560 ie
->cursor_visible
= !ie
->cursor_visible
;
562 goc_item_invalidate (item
);
567 item_edit_cursor_blink_stop (GnmItemEdit
*ie
)
569 if (ie
->blink_timer
!= 0) {
570 g_source_remove (ie
->blink_timer
);
576 item_edit_cursor_blink_start (GnmItemEdit
*ie
)
581 g_object_get (gtk_widget_get_settings (
582 GTK_WIDGET (ie
->item
.canvas
)),
583 "gtk-cursor-blink-time", &blink_time
,
584 "gtk-cursor-blink", &blink
,
587 ie
->blink_timer
= g_timeout_add ( blink_time
,
588 (GSourceFunc
) cb_item_edit_cursor_blink
, ie
);
592 item_edit_realize (GocItem
*item
)
594 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
599 parent_class
->realize (item
);
601 sheet
= scg_sheet (ie
->scg
);
603 g_signal_connect_object (G_OBJECT (scg_wbcg (ie
->scg
)),
605 G_CALLBACK (goc_item_bounds_changed
), G_OBJECT (ie
),
608 g_signal_connect_object (G_OBJECT (gtk_widget_get_parent (GTK_WIDGET (ie
->entry
))),
610 G_CALLBACK (goc_item_bounds_changed
), G_OBJECT (ie
),
613 g_signal_connect_object (G_OBJECT (ie
->entry
),
615 G_CALLBACK (cb_entry_key_press
), G_OBJECT (ie
),
616 G_CONNECT_AFTER
|G_CONNECT_SWAPPED
);
618 g_signal_connect_object (G_OBJECT (ie
->entry
),
619 "notify::cursor-position",
620 G_CALLBACK (cb_entry_cursor_event
), G_OBJECT (ie
),
621 G_CONNECT_AFTER
|G_CONNECT_SWAPPED
);
623 pane
= GNM_PANE (item
->canvas
);
624 scale
= item
->canvas
->pixels_per_unit
;
625 ie
->style
= gnm_style_dup
626 (sheet_style_get (sheet
, ie
->pos
.col
, ie
->pos
.row
));
627 ie
->gfont
= gnm_style_get_font
629 gtk_widget_get_pango_context (GTK_WIDGET (pane
)));
630 gnm_font_ref (ie
->gfont
);
632 if (gnm_style_get_align_h (ie
->style
) == GNM_HALIGN_GENERAL
)
633 gnm_style_set_align_h (ie
->style
, GNM_HALIGN_LEFT
);
635 /* move inwards 1 pixel from the grid line */
636 item
->y0
= (1 + pane
->first_offset
.y
+
637 scg_colrow_distance_get (ie
->scg
, FALSE
,
639 ie
->pos
.row
)) / scale
;
640 item
->x0
= (1 + pane
->first_offset
.x
+
641 scg_colrow_distance_get (ie
->scg
, TRUE
,
643 ie
->pos
.col
)) / scale
;
645 item
->x1
= item
->x0
+ 1 / scale
;
646 item
->y1
= item
->y0
+ 1 / scale
;
648 ie
->layout
= gtk_widget_create_pango_layout (GTK_WIDGET (item
->canvas
),
651 pango_layout_set_alignment (ie
->layout
,
656 item_edit_cursor_blink_start (ie
);
660 item_edit_unrealize (GocItem
*item
)
662 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
664 item_edit_cursor_blink_stop (ie
);
666 /* to destroy the feedback ranges */
667 SCG_FOREACH_PANE (ie
->scg
, pane
,
668 gnm_pane_expr_cursor_stop (pane
););
670 g_clear_object (&ie
->layout
);
672 if (ie
->gfont
!= NULL
) {
673 gnm_font_unref (ie
->gfont
);
676 if (ie
->style
!= NULL
) {
677 gnm_style_unref (ie
->style
);
681 parent_class
->unrealize (item
);
685 gnm_item_edit_init (GnmItemEdit
*ie
)
692 ie
->cursor_visible
= TRUE
;
698 item_edit_set_property (GObject
*gobject
, guint param_id
,
699 GValue
const *value
, GParamSpec
*pspec
)
701 GnmItemEdit
*ie
= GNM_ITEM_EDIT (gobject
);
704 case ARG_SHEET_CONTROL_GUI
: {
705 /* We can only set the sheet-control-gui once */
706 g_return_if_fail (ie
->scg
== NULL
);
708 ie
->scg
= GNM_SCG (g_value_get_object (value
));
709 ie
->pos
= scg_view (ie
->scg
)->edit_pos
;
710 ie
->entry
= wbcg_get_entry (scg_wbcg (ie
->scg
));
714 default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject
, param_id
, pspec
);
715 return; /* NOTE : RETURN */
720 gnm_item_edit_class_init (GObjectClass
*gobject_class
)
722 GocItemClass
*item_class
= (GocItemClass
*) gobject_class
;
724 parent_class
= g_type_class_peek_parent (gobject_class
);
726 gobject_class
->set_property
= item_edit_set_property
;
728 g_object_class_install_property (gobject_class
, ARG_SHEET_CONTROL_GUI
,
729 g_param_spec_object ("SheetControlGUI",
730 P_("SheetControlGUI"),
731 P_("The sheet control gui controlling the item"),
733 /* resist the urge to use G_PARAM_CONSTRUCT_ONLY
734 * We are going through goc_item_new, which
735 * calls g_object_new assigns the parent pointer before
736 * setting the construction parameters */
737 GSF_PARAM_STATIC
| G_PARAM_WRITABLE
));
739 /* GocItem method overrides */
740 item_class
->realize
= item_edit_realize
;
741 item_class
->unrealize
= item_edit_unrealize
;
742 item_class
->draw
= item_edit_draw
;
743 item_class
->distance
= item_edit_distance
;
744 item_class
->update_bounds
= item_edit_update_bounds
;
745 item_class
->button_pressed
= item_edit_button_pressed
;
746 item_class
->enter_notify
= item_edit_enter_notify
;
747 item_class
->motion
= item_edit_motion
;
748 item_class
->button_released
= item_edit_button_released
;
751 GSF_CLASS (GnmItemEdit
, gnm_item_edit
,
752 gnm_item_edit_class_init
, gnm_item_edit_init
,