1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * item-edit.c : Edit facilities for worksheets.
5 * (C) 1999-2004 Miguel de Icaza & Jody Goldberg
7 * This module provides:
8 * * Integration of an in-sheet text editor (GtkEntry) with the Workbook
9 * GtkEntry as a canvas item.
11 * * Feedback on expressions in the spreadsheet (referenced cells or
12 * ranges are highlighted on the spreadsheet).
14 #include <gnumeric-config.h>
17 #include "item-edit.h"
18 #include "gnm-pane-impl.h"
20 #include "item-cursor.h"
21 #include "sheet-control-gui-priv.h"
23 #include "sheet-view.h"
24 #include "sheet-style.h"
25 #include "sheet-merge.h"
29 #include "style-font.h"
30 #include "style-color.h"
32 #include "parse-util.h"
36 #include "widgets/gnumeric-expr-entry.h"
37 #define GNUMERIC_ITEM "EDIT"
40 #include <gsf/gsf-impl-utils.h>
42 #include <goffice/goffice.h>
44 static GocItemClass
*parent_class
;
50 GtkEntry
*entry
; /* Utility pointer to the workbook entry */
56 gboolean cursor_visible
;
64 typedef GocItemClass GnmItemEditClass
;
66 /* The arguments we take */
69 ARG_SHEET_CONTROL_GUI
/* The SheetControlGUI * argument */
73 get_top_left (GnmItemEdit
const *ie
, int *top
, int *left
, PangoDirection dir
)
75 GnmVAlign
const align
= gnm_style_get_align_v (ie
->style
);
76 GocItem
*item
= GOC_ITEM (ie
);
77 GocCanvas
*canvas
= item
->canvas
;
78 double l
= ((goc_canvas_get_direction (canvas
) == GOC_DIRECTION_LTR
&& dir
== PANGO_DIRECTION_RTL
)
79 || (goc_canvas_get_direction (canvas
) == GOC_DIRECTION_RTL
&& dir
!= PANGO_DIRECTION_RTL
))?
80 item
->x1
- 1: item
->x0
;
82 goc_canvas_c2w (canvas
, l
, item
->y0
, left
, top
);
84 if (align
== GNM_VALIGN_CENTER
|| align
== GNM_VALIGN_DISTRIBUTED
||
85 align
== GNM_VALIGN_BOTTOM
) {
86 int text_height
, height
= (int)(ie
->item
.y1
- ie
->item
.y0
) * canvas
->pixels_per_unit
;
87 pango_layout_get_pixel_size (ie
->layout
, NULL
, &text_height
);
88 *top
+= (align
!= GNM_VALIGN_BOTTOM
)
89 ? (height
- text_height
)/2
90 : (height
- text_height
);
95 gnm_apply_attribute_list_cb (PangoAttribute
*attribute
,
98 PangoAttrList
*attrs
= data
;
99 if (attribute
->klass
->type
== PANGO_ATTR_FOREGROUND
) {
100 PangoAttribute
*copy
= pango_attribute_copy (attribute
);
101 pango_attr_list_change (attrs
, copy
);
107 gnm_apply_attribute_list (PangoAttrList
*attrs
, PangoAttrList
*added_attrs
)
109 if (added_attrs
== NULL
)
111 pango_attr_list_unref (pango_attr_list_filter (added_attrs
,
112 gnm_apply_attribute_list_cb
,
117 item_edit_draw (GocItem
const *item
, cairo_t
*cr
)
119 GnmItemEdit
const *ie
= GNM_ITEM_EDIT (item
);
120 GtkStyleContext
*context
= goc_item_get_style_context (item
);
123 int x0
, y0
, x1
, y1
; /* in widget coordinates */
125 PangoRectangle pos
, weak
;
126 char const *text
= gtk_entry_get_text (ie
->entry
);
128 PangoDirection dir
= pango_find_base_dir (text
, -1);
129 PangoAttrList
*entry_attributes
130 = g_object_get_data(G_OBJECT (ie
->entry
),
131 "gnm:range-attributes");
133 if (entry_attributes
!= NULL
) {
134 if (go_pango_attr_list_is_empty (entry_attributes
))
135 entry_attributes
= NULL
;
137 entry_attributes
= pango_attr_list_ref (entry_attributes
);
140 get_top_left (ie
, &top
, &left
, dir
);
141 if (goc_canvas_get_direction (item
->canvas
) == GOC_DIRECTION_RTL
) {
142 goc_canvas_c2w (item
->canvas
, item
->x1
, item
->y0
, &x0
, &y0
);
143 goc_canvas_c2w (item
->canvas
, item
->x0
, item
->y1
, &x1
, &y1
);
145 goc_canvas_c2w (item
->canvas
, item
->x0
, item
->y0
, &x0
, &y0
);
146 goc_canvas_c2w (item
->canvas
, item
->x1
, item
->y1
, &x1
, &y1
);
151 cairo_rectangle (cr
, x0
, y0
, x1
- x0
, y1
- y0
);
152 /* avoid a weak/strong cursor to extend outside the item,
153 a better fix would be to have enough room for cursors */
155 if (gnm_pattern_background_set (ie
->style
, cr
, FALSE
, NULL
)) {
156 cairo_rectangle (cr
, x0
, y0
, x1
- x0
, y1
- y0
);
159 gtk_render_background (context
, cr
, x0
, y0
, x1
- x0
, y1
- y0
);
162 /* set the default color */
163 gnm_style_context_get_color (context
, GTK_STATE_FLAG_NORMAL
, &fcolor
);
164 gdk_cairo_set_source_rgba (cr
, &fcolor
);
165 color
= go_color_from_gdk_rgba (&fcolor
, NULL
);
167 if (dir
== PANGO_DIRECTION_RTL
) {
168 pango_layout_get_pixel_extents (ie
->layout
, NULL
, &pos
);
169 left
-= pos
.width
+ GNM_COL_MARGIN
/ goc_canvas_get_pixels_per_unit (item
->canvas
);
171 cairo_move_to (cr
, left
, top
);
172 gtk_editable_get_selection_bounds (GTK_EDITABLE (ie
->entry
), &start
, &end
);
174 PangoAttribute
*attr
;
175 PangoAttrList
*orig
= pango_attr_list_ref (pango_layout_get_attributes (ie
->layout
)),
176 *attrs
= pango_attr_list_copy (orig
);
177 start
= g_utf8_offset_to_pointer (text
, start
) - text
;
178 end
= g_utf8_offset_to_pointer (text
, end
) - text
;
179 color
= gnm_style_get_back_color (ie
->style
)->go_color
;
180 attr
= go_color_to_pango (color
, FALSE
);
181 attr
->start_index
= start
;
182 attr
->end_index
= end
;
183 pango_attr_list_change (attrs
, attr
);
184 color
= gnm_style_get_font_color (ie
->style
)->go_color
;
185 attr
= go_color_to_pango (color
, TRUE
);
186 attr
->start_index
= start
;
187 attr
->end_index
= end
;
188 pango_attr_list_change (attrs
, attr
);
189 gnm_apply_attribute_list (attrs
, entry_attributes
);
190 pango_layout_set_attributes (ie
->layout
, attrs
);
191 pango_attr_list_unref (attrs
);
192 pango_cairo_show_layout (cr
, ie
->layout
);
193 pango_layout_set_attributes (ie
->layout
, orig
);
194 pango_attr_list_unref (orig
);
195 } else if (entry_attributes
!= NULL
) {
196 PangoAttrList
*orig
= pango_attr_list_ref (pango_layout_get_attributes (ie
->layout
)),
197 *attrs
= pango_attr_list_copy (orig
);
198 gnm_apply_attribute_list (attrs
, entry_attributes
);
199 pango_layout_set_attributes (ie
->layout
, attrs
);
200 pango_attr_list_unref (attrs
);
201 pango_cairo_show_layout (cr
, ie
->layout
);
202 pango_layout_set_attributes (ie
->layout
, orig
);
203 pango_attr_list_unref (orig
);
205 pango_cairo_show_layout (cr
, ie
->layout
);
207 pango_attr_list_unref (entry_attributes
);
209 if (ie
->cursor_visible
) {
210 int cursor_pos
= gtk_editable_get_position (GTK_EDITABLE (ie
->entry
));
211 double incr
= (dir
== PANGO_DIRECTION_RTL
)? -.5: .5, x
, ytop
, ybottom
;
212 pango_layout_get_cursor_pos (ie
->layout
,
213 g_utf8_offset_to_pointer (text
, cursor_pos
) - text
, &pos
, &weak
);
214 cairo_set_line_width (cr
, 1.);
215 cairo_set_dash (cr
, NULL
, 0, 0.);
216 cairo_set_line_cap (cr
, CAIRO_LINE_CAP_BUTT
);
217 cairo_set_line_join (cr
, CAIRO_LINE_JOIN_MITER
);
218 cairo_set_source_rgba (cr
, GO_COLOR_TO_CAIRO (gnm_style_get_back_color (ie
->style
)->go_color
^ 0xffffff00));
219 x
= left
+ PANGO_PIXELS (pos
.x
) + incr
;
220 ytop
= top
+ PANGO_PIXELS (pos
.y
);
221 ybottom
= top
+ PANGO_PIXELS (pos
.y
+ pos
.height
) - 1;
222 cairo_move_to (cr
, x
, ytop
);
223 cairo_line_to (cr
, x
, ybottom
);
225 if (weak
.x
!= pos
.x
) {
226 double w
= (ybottom
- ytop
) / 4.;
227 GOColor color1
= color
^ 0xffffff00;
229 cairo_move_to (cr
, x
, ybottom
);
230 cairo_line_to (cr
, x
+ w
* incr
, ybottom
- w
/ 2.);
231 cairo_line_to (cr
, x
, ybottom
- w
);
232 cairo_close_path (cr
);
234 color
= GO_COLOR_INTERPOLATE (color
, color1
, 0.5);
235 x
= left
+ PANGO_PIXELS (weak
.x
) - incr
;
236 ytop
= top
+ PANGO_PIXELS (weak
.y
);
237 ybottom
= top
+ PANGO_PIXELS (weak
.y
+ weak
.height
) - 1;
238 cairo_set_source_rgba (cr
, GO_COLOR_TO_CAIRO (color
));
239 cairo_move_to (cr
, x
, ytop
);
240 cairo_line_to (cr
, x
, ybottom
);
243 cairo_move_to (cr
, x
, ybottom
);
244 cairo_line_to (cr
, x
- w
* incr
, ybottom
- w
/ 2.);
245 cairo_line_to (cr
, x
, ybottom
- w
);
246 cairo_close_path (cr
);
254 item_edit_distance (GocItem
*item
, double cx
, double cy
,
255 GocItem
**actual_item
)
258 if ((cx
< item
->x0
) || (cy
< item
->y0
) || (cx
>= item
->x1
) || (cy
>= item
->y1
))
266 item_edit_enter_notify (GocItem
*item
, G_GNUC_UNUSED
double x
, G_GNUC_UNUSED
double y
)
268 gnm_widget_set_cursor_type (GTK_WIDGET (item
->canvas
), GDK_XTERM
);
273 item_edit_button_pressed (GocItem
*item
, int button
, double x
, double y
)
276 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
277 GtkEditable
*ed
= GTK_EDITABLE (ie
->entry
);
278 int target_index
, trailing
;
279 char const *text
= pango_layout_get_text (ie
->layout
);
280 PangoDirection dir
= pango_find_base_dir (text
, -1);
282 GocDirection cdir
= goc_canvas_get_direction (item
->canvas
);
284 if (cdir
== GOC_DIRECTION_RTL
)
285 x
= item
->x1
- x
- 1;
289 if (dir
== PANGO_DIRECTION_RTL
) {
290 pango_layout_get_pixel_extents (ie
->layout
, NULL
, &pos
);
291 x
-= item
->x1
- item
->x0
- (pos
.width
292 + 2 * GNM_COL_MARGIN
) / goc_canvas_get_pixels_per_unit (item
->canvas
);
294 /* the layout might be zoomed, we need to adjust x and y accordingly */
295 x
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
296 y
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
298 if (pango_layout_xy_to_index (ie
->layout
,
299 x
* PANGO_SCALE
, y
* PANGO_SCALE
,
300 &target_index
, &trailing
)) {
301 int preedit
= GNM_PANE (item
->canvas
)->preedit_length
;
302 gint cur_index
= gtk_editable_get_position (ed
);
303 cur_index
= g_utf8_offset_to_pointer (text
, cur_index
) - text
;
305 if (target_index
>= cur_index
&& preedit
> 0) {
306 if (target_index
< (cur_index
+ preedit
)) {
307 target_index
= cur_index
;
310 target_index
-= preedit
;
313 /* the click occured after text end (#388342) */
314 target_index
= strlen (text
);
317 ie
->sel_start
= g_utf8_pointer_to_offset (text
, text
+ target_index
) + trailing
;
318 gtk_editable_set_position (GTK_EDITABLE (ie
->entry
), ie
->sel_start
);
327 item_edit_motion (GocItem
*item
, double x
, double y
)
329 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
330 if (ie
->sel_start
>= 0) {
331 GtkEditable
*ed
= GTK_EDITABLE (ie
->entry
);
332 int target_index
, trailing
;
333 char const *text
= pango_layout_get_text (ie
->layout
);
334 PangoDirection dir
= pango_find_base_dir (text
, -1);
336 GocDirection cdir
= goc_canvas_get_direction (item
->canvas
);
338 if (cdir
== GOC_DIRECTION_RTL
)
339 x
= item
->x1
- x
- 1;
343 if (dir
== PANGO_DIRECTION_RTL
) {
344 pango_layout_get_pixel_extents (ie
->layout
, NULL
, &pos
);
345 x
-= item
->x1
- item
->x0
- (pos
.width
346 + 2 * GNM_COL_MARGIN
) / goc_canvas_get_pixels_per_unit (item
->canvas
);
348 /* the layout might be zoomed, we need to adjust x and y accordingly */
349 x
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
350 y
*= goc_canvas_get_pixels_per_unit (item
->canvas
);
352 if (pango_layout_xy_to_index (ie
->layout
,
353 x
* PANGO_SCALE
, y
* PANGO_SCALE
,
354 &target_index
, &trailing
)) {
355 int preedit
= GNM_PANE (item
->canvas
)->preedit_length
;
356 gint cur_index
= gtk_editable_get_position (ed
);
357 cur_index
= g_utf8_offset_to_pointer (text
, cur_index
) - text
;
359 if (target_index
>= cur_index
&& preedit
> 0) {
360 if (target_index
< (cur_index
+ preedit
)) {
361 target_index
= cur_index
;
364 target_index
-= preedit
;
367 /* the click occured after text end (#388342) */
368 target_index
= strlen (text
);
371 target_index
= g_utf8_pointer_to_offset (text
, text
+ target_index
) + trailing
;
372 if (target_index
> ie
->sel_start
)
373 gtk_editable_select_region (GTK_EDITABLE (ie
->entry
), ie
->sel_start
, target_index
);
375 gtk_editable_select_region (GTK_EDITABLE (ie
->entry
), target_index
, ie
->sel_start
);
376 goc_item_invalidate (item
);
384 item_edit_button_released (GocItem
*item
, G_GNUC_UNUSED
int button
,
385 G_GNUC_UNUSED
double x
, G_GNUC_UNUSED
double y
)
387 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
388 if (ie
->sel_start
>= 0) {
396 item_edit_update_bounds (GocItem
*item
)
398 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
399 double scale
= item
->canvas
->pixels_per_unit
;
401 if (ie
->gfont
!= NULL
) {
402 GtkWidget
const *canvas
= GTK_WIDGET (item
->canvas
);
403 GnmPane
const *pane
= GNM_PANE (item
->canvas
);
404 ColRowInfo
const *ci
;
405 Sheet
const *sheet
= scg_sheet (ie
->scg
);
406 GnmFont
const *gfont
= ie
->gfont
;
407 GnmRange
const *merged
;
408 int col
, tmp
, width
, height
, col_size
;
409 char const *text
, *entered_text
;
410 PangoAttrList
*attrs
;
411 PangoAttribute
*attr
;
412 int cursor_pos
= gtk_editable_get_position (GTK_EDITABLE (ie
->entry
));
414 GocDirection cdir
= goc_canvas_get_direction (item
->canvas
);
416 entered_text
= gtk_entry_get_text (ie
->entry
);
417 text
= wbcg_edit_get_display_text (scg_wbcg (ie
->scg
));
418 pango_layout_set_text (ie
->layout
, text
, -1);
419 dir
= pango_find_base_dir (text
, -1);
421 pango_layout_set_font_description (ie
->layout
, gfont
->go
.font
->desc
);
422 pango_layout_set_wrap (ie
->layout
, PANGO_WRAP_WORD_CHAR
);
423 pango_layout_set_width (ie
->layout
, (int)(item
->x1
- item
->x0
)*PANGO_SCALE
);
425 attrs
= wbcg_edit_get_markup (scg_wbcg (ie
->scg
), TRUE
);
427 attrs
= pango_attr_list_copy (attrs
);
429 attrs
= gnm_style_generate_attrs_full (ie
->style
);
431 /* reverse video the auto completion text */
432 if (entered_text
!= NULL
&& entered_text
!= text
) {
433 int const start
= strlen (entered_text
);
434 GnmColor
const *color
= gnm_style_get_font_color (ie
->style
);
435 attr
= go_color_to_pango (color
->go_color
, FALSE
);
436 attr
->start_index
= start
;
437 attr
->end_index
= G_MAXINT
;
438 pango_attr_list_insert (attrs
, attr
);
440 color
= gnm_style_get_back_color (ie
->style
);
441 attr
= go_color_to_pango (color
->go_color
, TRUE
);
442 attr
->start_index
= start
;
443 attr
->end_index
= G_MAXINT
;
444 pango_attr_list_insert (attrs
, attr
);
446 pango_attr_list_insert_before (attrs
,
447 pango_attr_scale_new (scale
));
449 pango_layout_set_attributes (ie
->layout
, attrs
);
450 pango_attr_list_unref (attrs
);
452 go_pango_translate_layout (ie
->layout
);
454 if (pane
->preedit_length
) {
455 PangoAttrList
*tmp_attrs
= pango_attr_list_new ();
456 pango_attr_list_splice (tmp_attrs
, pane
->preedit_attrs
,
457 g_utf8_offset_to_pointer (text
, cursor_pos
) - text
,
458 g_utf8_offset_to_pointer (text
, cursor_pos
+ pane
->preedit_length
) - text
);
459 pango_layout_set_attributes (ie
->layout
, tmp_attrs
);
460 pango_attr_list_unref (tmp_attrs
);
463 pango_layout_set_width (ie
->layout
, -1);
464 pango_layout_get_pixel_size (ie
->layout
, &width
, &height
);
467 if (NULL
== (merged
= gnm_sheet_merge_is_corner (sheet
, &ie
->pos
))) {
468 ci
= sheet_col_get_info (sheet
, col
);
469 g_return_if_fail (ci
!= NULL
);
470 col_size
= ci
->size_pixels
;
472 col_size
= scg_colrow_distance_get (ie
->scg
, TRUE
,
473 merged
->start
.col
, merged
->end
.col
+1);
475 /* both margins and the gridline */
476 col_size
-= GNM_COL_MARGIN
+ GNM_COL_MARGIN
+ 1;
478 /* far corner based on the span size
479 * - margin on each end
480 * - the bound excludes the far point => +1 */
482 col
= merged
->end
.col
;
484 if ((dir
== PANGO_DIRECTION_RTL
&& cdir
== GOC_DIRECTION_RTL
) ||
485 (dir
!= PANGO_DIRECTION_RTL
&& cdir
== GOC_DIRECTION_LTR
)) {
488 while (col_size
< width
&&
489 col
<= pane
->last_full
.col
&&
490 col
< gnm_sheet_get_last_col (sheet
)) {
491 ci
= sheet_col_get_info (sheet
, ++col
);
493 g_return_if_fail (ci
!= NULL
);
496 col_size
+= ci
->size_pixels
;
498 gtk_widget_get_allocation (GTK_WIDGET (canvas
), &a
);
499 tmp
= (pane
->first_offset
.x
+ a
.width
) / scale
;
500 item
->x1
= item
->x0
+ (col_size
+ GNM_COL_MARGIN
+ GNM_COL_MARGIN
+ 1) / scale
;
502 if (item
->x1
>= tmp
) {
504 pango_layout_set_width (ie
->layout
, (item
->x1
- item
->x0
+ 1)*PANGO_SCALE
);
505 pango_layout_get_pixel_size (ie
->layout
, &width
, &height
);
508 item
->x1
= (1 + pane
->first_offset
.x
+
509 scg_colrow_distance_get (ie
->scg
, TRUE
,
511 ie
->pos
.col
+1)) / scale
;
512 while (col_size
< width
&&
513 col
> pane
->first
.col
&&
515 ci
= sheet_col_get_info (sheet
, --col
);
517 g_return_if_fail (ci
!= NULL
);
520 col_size
+= ci
->size_pixels
;
522 if (col_size
< width
)
524 tmp
= pane
->first_offset
.x
/ scale
;
525 item
->x0
= item
->x1
- (col_size
+ GNM_COL_MARGIN
+ GNM_COL_MARGIN
+ 1) / scale
;
526 if (item
->x0
<= tmp
) {
528 pango_layout_set_width (ie
->layout
, (item
->x1
- item
->x0
+ 1)*PANGO_SCALE
);
529 pango_layout_get_pixel_size (ie
->layout
, &width
, &height
);
533 tmp
= scg_colrow_distance_get (ie
->scg
, FALSE
, ie
->pos
.row
,
534 (merged
? merged
->end
.row
: ie
->pos
.row
) + 1) - 1;
535 item
->y1
= item
->y0
+ (MAX (height
, tmp
)) / scale
;
540 cb_entry_key_press (GocItem
*item
)
542 goc_item_bounds_changed (item
);
547 cb_entry_cursor_event (GocItem
*item
)
549 /* ensure we draw a cursor when moving quickly no matter what the
550 * current state is */
551 GNM_ITEM_EDIT (item
)->cursor_visible
= TRUE
;
552 goc_item_invalidate (item
);
558 cb_item_edit_cursor_blink (GnmItemEdit
*ie
)
560 GocItem
*item
= GOC_ITEM (ie
);
562 ie
->cursor_visible
= !ie
->cursor_visible
;
564 goc_item_invalidate (item
);
569 item_edit_cursor_blink_stop (GnmItemEdit
*ie
)
571 if (ie
->blink_timer
!= 0) {
572 g_source_remove (ie
->blink_timer
);
578 item_edit_cursor_blink_start (GnmItemEdit
*ie
)
583 g_object_get (gtk_widget_get_settings (
584 GTK_WIDGET (ie
->item
.canvas
)),
585 "gtk-cursor-blink-time", &blink_time
,
586 "gtk-cursor-blink", &blink
,
589 ie
->blink_timer
= g_timeout_add ( blink_time
,
590 (GSourceFunc
) cb_item_edit_cursor_blink
, ie
);
594 item_edit_realize (GocItem
*item
)
596 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
601 parent_class
->realize (item
);
603 sheet
= scg_sheet (ie
->scg
);
605 g_signal_connect_object (G_OBJECT (scg_wbcg (ie
->scg
)),
607 G_CALLBACK (goc_item_bounds_changed
), G_OBJECT (ie
),
610 g_signal_connect_object (G_OBJECT (gtk_widget_get_parent (GTK_WIDGET (ie
->entry
))),
612 G_CALLBACK (goc_item_bounds_changed
), G_OBJECT (ie
),
615 g_signal_connect_object (G_OBJECT (ie
->entry
),
617 G_CALLBACK (cb_entry_key_press
), G_OBJECT (ie
),
618 G_CONNECT_AFTER
|G_CONNECT_SWAPPED
);
620 g_signal_connect_object (G_OBJECT (ie
->entry
),
621 "notify::cursor-position",
622 G_CALLBACK (cb_entry_cursor_event
), G_OBJECT (ie
),
623 G_CONNECT_AFTER
|G_CONNECT_SWAPPED
);
625 pane
= GNM_PANE (item
->canvas
);
626 scale
= item
->canvas
->pixels_per_unit
;
627 ie
->style
= gnm_style_dup
628 (sheet_style_get (sheet
, ie
->pos
.col
, ie
->pos
.row
));
629 ie
->gfont
= gnm_style_get_font
631 gtk_widget_get_pango_context (GTK_WIDGET (pane
)));
632 gnm_font_ref (ie
->gfont
);
634 if (gnm_style_get_align_h (ie
->style
) == GNM_HALIGN_GENERAL
)
635 gnm_style_set_align_h (ie
->style
, GNM_HALIGN_LEFT
);
637 /* move inwards 1 pixel from the grid line */
638 item
->y0
= (1 + pane
->first_offset
.y
+
639 scg_colrow_distance_get (ie
->scg
, FALSE
,
641 ie
->pos
.row
)) / scale
;
642 item
->x0
= (1 + pane
->first_offset
.x
+
643 scg_colrow_distance_get (ie
->scg
, TRUE
,
645 ie
->pos
.col
)) / scale
;
647 item
->x1
= item
->x0
+ 1 / scale
;
648 item
->y1
= item
->y0
+ 1 / scale
;
650 ie
->layout
= gtk_widget_create_pango_layout (GTK_WIDGET (item
->canvas
),
653 pango_layout_set_alignment (ie
->layout
,
658 item_edit_cursor_blink_start (ie
);
662 item_edit_unrealize (GocItem
*item
)
664 GnmItemEdit
*ie
= GNM_ITEM_EDIT (item
);
666 item_edit_cursor_blink_stop (ie
);
668 /* to destroy the feedback ranges */
669 SCG_FOREACH_PANE (ie
->scg
, pane
,
670 gnm_pane_expr_cursor_stop (pane
););
672 g_clear_object (&ie
->layout
);
674 if (ie
->gfont
!= NULL
) {
675 gnm_font_unref (ie
->gfont
);
678 if (ie
->style
!= NULL
) {
679 gnm_style_unref (ie
->style
);
683 parent_class
->unrealize (item
);
687 gnm_item_edit_init (GnmItemEdit
*ie
)
694 ie
->cursor_visible
= TRUE
;
700 item_edit_set_property (GObject
*gobject
, guint param_id
,
701 GValue
const *value
, GParamSpec
*pspec
)
703 GnmItemEdit
*ie
= GNM_ITEM_EDIT (gobject
);
706 case ARG_SHEET_CONTROL_GUI
: {
707 /* We can only set the sheet-control-gui once */
708 g_return_if_fail (ie
->scg
== NULL
);
710 ie
->scg
= GNM_SCG (g_value_get_object (value
));
711 ie
->pos
= scg_view (ie
->scg
)->edit_pos
;
712 ie
->entry
= wbcg_get_entry (scg_wbcg (ie
->scg
));
716 default: G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject
, param_id
, pspec
);
717 return; /* NOTE : RETURN */
722 gnm_item_edit_class_init (GObjectClass
*gobject_class
)
724 GocItemClass
*item_class
= (GocItemClass
*) gobject_class
;
726 parent_class
= g_type_class_peek_parent (gobject_class
);
728 gobject_class
->set_property
= item_edit_set_property
;
730 g_object_class_install_property (gobject_class
, ARG_SHEET_CONTROL_GUI
,
731 g_param_spec_object ("SheetControlGUI",
732 P_("SheetControlGUI"),
733 P_("The sheet control gui controlling the item"),
735 /* resist the urge to use G_PARAM_CONSTRUCT_ONLY
736 * We are going through goc_item_new, which
737 * calls g_object_new assigns the parent pointer before
738 * setting the construction parameters */
739 GSF_PARAM_STATIC
| G_PARAM_WRITABLE
));
741 /* GocItem method overrides */
742 item_class
->realize
= item_edit_realize
;
743 item_class
->unrealize
= item_edit_unrealize
;
744 item_class
->draw
= item_edit_draw
;
745 item_class
->distance
= item_edit_distance
;
746 item_class
->update_bounds
= item_edit_update_bounds
;
747 item_class
->button_pressed
= item_edit_button_pressed
;
748 item_class
->enter_notify
= item_edit_enter_notify
;
749 item_class
->motion
= item_edit_motion
;
750 item_class
->button_released
= item_edit_button_released
;
753 GSF_CLASS (GnmItemEdit
, gnm_item_edit
,
754 gnm_item_edit_class_init
, gnm_item_edit_init
,