lazarus/lcl/interfaces/gtk2/gtk2object.inc
mattias 730a67c8e1 fixed button return key
git-svn-id: trunk@5500 -
2004-05-22 14:35:33 +00:00

1423 lines
50 KiB
PHP

{******************************************************************************
TGtk2WidgetSet
******************************************************************************
*****************************************************************************
* *
* This file is part of the Lazarus Component Library (LCL) *
* *
* See the file COPYING.LCL, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
}
{$IFOPT C-}
// Uncomment for local trace
// {$C+}
// {$DEFINE ASSERT_IS_ON}
{$ENDIF}
function GTK2FocusCB( widget: PGtkWidget; event:PGdkEventFocus;
data: gPointer) : GBoolean; cdecl;
var
Status : gBoolean;
begin
Status := GTKFocusCB(Widget, Event, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
function GTK2FocusCBAfter(widget: PGtkWidget; event:PGdkEventFocus;
data: gPointer) : GBoolean; cdecl;
var
Status : gBoolean;
begin
Status := GTKFocusCBAfter(Widget, Event, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
function gtk2HideCB( widget: PGtkWidget; data: gPointer) : GBoolean; cdecl;
var
Status : GBoolean;
begin
Status := gtkHideCB(Widget, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
function GTK2KeyUpDown(Widget: PGtkWidget; Event : pgdkeventkey;
Data: gPointer) : GBoolean; cdecl;
var
Status : gBoolean;
begin
Status := GTKKeyUpDown(Widget, Event, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
function GTK2KillFocusCB(widget: PGtkWidget; event:PGdkEventFocus;
data: gPointer) : GBoolean; cdecl;
var
Status : gBoolean;
begin
Status := GTKKillFocusCB(Widget, Event, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
function GTK2KillFocusCBAfter(widget: PGtkWidget; event:PGdkEventFocus;
data: gPointer) : GBoolean; cdecl;
var
Status : gBoolean;
begin
Status := GTKKillFocusCBAfter(Widget, Event, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
function gtk2showCB( widget: PGtkWidget; data: gPointer) : GBoolean; cdecl;
var
Status : GBoolean;
begin
Status := gtkshowCB(Widget, Data);
if GtkWidgetIsA(Widget,GTK_APIWIDGETCLIENT_TYPE) then
Result := Status
else
Result := False;
end;
Procedure gtk_clb_toggle(cellrenderertoggle : PGtkCellRendererToggle; arg1 : PGChar;
WinControl: TWinControl); cdecl;
var
aWidget : PGTKWidget;
aTreeModel : PGtkTreeModel;
aTreeIter : TGtkTreeIter;
value : pgValue;
begin
aWidget := GetWidgetInfo(Pointer(WinControl.Handle), True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model (GTK_TREE_VIEW(aWidget));
if (gtk_tree_model_get_iter_from_string (aTreeModel, @aTreeIter, arg1)) then begin
aTreeIter.stamp := GTK_LIST_STORE (aTreeModel)^.stamp; //strange hack
value := g_new0(SizeOf(TgValue), 1);
gtk_tree_model_get_value(aTreeModel, @aTreeIter, 0, value);
g_value_set_boolean(value, not g_value_get_boolean(value));
gtk_list_store_set_value (GTK_LIST_STORE (aTreeModel), @aTreeIter, 0, value);
g_value_unset(value);
g_free(value);
end;
end;
Procedure gtk_clb_toggle_row_activated(treeview : PGtkTreeView; arg1 : PGtkTreePath;
arg2 : PGtkTreeViewColumn; data : gpointer); cdecl;
var
aTreeModel : PGtkTreeModel;
aTreeIter : TGtkTreeIter;
value : PGValue;
begin
aTreeModel := gtk_tree_view_get_model (treeview);
if (gtk_tree_model_get_iter (aTreeModel, @aTreeIter, arg1)) then begin
aTreeIter.stamp := GTK_LIST_STORE (aTreeModel)^.stamp; //strange hack
value := g_new0(SizeOf(TgValue), 1);
gtk_tree_model_get_value(aTreeModel, @aTreeIter, 0, value);
g_value_set_boolean(value, not g_value_get_boolean(value));
gtk_list_store_set_value (GTK_LIST_STORE (aTreeModel), @aTreeIter, 0, value);
g_value_unset(value);
g_free(value);
end;
end;
{$IfNDef GTK2_2}
Procedure gtkTreeSelectionCountSelectedRows(model : PGtkTreeModel; path : PGtkTreePath;
iter : PGtkTreeIter; data : PGint); cdecl;
begin
If Assigned(Data) then
Inc(Data^);
end;
Type
PPGList = ^PGList;
Procedure gtkTreeSelectionGetSelectedRows(model : PGtkTreeModel; path : PGtkTreePath;
iter : PGtkTreeIter; data : PPGList); cdecl;
begin
If Assigned(Data) then
Data^ := g_list_append(Data^, gtk_tree_path_copy(path));
end;
{$EndIf}
{------------------------------------------------------------------------------
procedure TGtk2WidgetSet.AppendText(Sender: TObject; Str: PChar);
------------------------------------------------------------------------------}
procedure TGtk2WidgetSet.AppendText(Sender: TObject; Str: PChar);
var
Widget : PGtkWidget;
aTextBuffer : PGtkTextBuffer;
aTextIter1 : TGtkTextIter;
aTextIter2 : TGtkTextIter;
begin
if Str=nil then exit;
if (Sender is TWinControl) then begin
case TWinControl(Sender).fCompStyle of
csMemo:
begin
Widget:= GetWidgetInfo(Pointer(TWinControl(Sender).Handle), True)^.CoreWidget;
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
gtk_text_buffer_begin_user_action(aTextBuffer);
gtk_text_buffer_get_bounds(aTextBuffer, @aTextIter1, @aTextIter2);
gtk_text_buffer_insert(aTextBuffer, @aTextIter2, str, StrLen(str));
gtk_text_buffer_end_user_action(aTextBuffer);
end;
else
inherited AppendText(Sender, Str);
end;
end;
end;
function TGtk2WidgetSet.CreateComponent(Sender : TObject): THandle;
var
Caption : ansistring; // the caption of "Sender"
StrTemp : PChar; // same as "caption" but as PChar
TempWidget,
TempWidget2 : PGTKWidget; // pointer to gtk-widget (local use when neccessary)
p : pointer; // ptr to the newly created GtkWidget
CompStyle, // componentstyle (type) of GtkWidget which will be created
TempInt : Integer; // local use when neccessary
// - for csBitBtn
Box : Pointer; // currently only used for TBitBtn
pixmapwid : pGtkWidget; // currently only used for TBitBtn
label1 : pgtkwidget; // currently only used for TBitBtn
ParentForm: TCustomForm;
AccelText : PChar;
AccelKey : guint;
SetupProps : boolean;
AWindow: PGdkWindow;
liststore : PGtkListStore;
renderer : PGtkCellRenderer;
column : PGtkTreeViewColumn;
begin
p := nil;
SetupProps:= false;
CompStyle := GetCompStyle(Sender);
Caption := GetCaption(Sender);
strTemp := StrAlloc(length(Caption) + 1);
StrPCopy(strTemp, Caption);
case CompStyle of
csEdit :
begin
p := gtk_entry_new();
gtk_editable_set_editable (PGtkEditable(P), not TCustomEdit(Sender).ReadOnly);
gtk_widget_show_all(P);
end;
csListBox, csCheckListBox:
begin
p:= gtk_scrolled_window_new(nil, nil);
GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.hscrollbar, GTK_CAN_FOCUS);
GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.vscrollbar, GTK_CAN_FOCUS);
gtk_scrolled_window_set_policy(PGtkScrolledWindow(p),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_show(p);
if (CompStyle = csListBox) then
liststore := gtk_list_store_new (1, [G_TYPE_STRING, nil])
else
liststore := gtk_list_store_new (2, [G_TYPE_BOOLEAN, G_TYPE_STRING, nil]);
TempWidget:= gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
g_object_unref (G_OBJECT (liststore));
TempInt := 0;
if (CompStyle = csCheckListBox) then begin
renderer := gtk_cell_renderer_toggle_new();
column := gtk_tree_view_column_new_with_attributes('', renderer, ['active', 0, nil]);
gtk_cell_renderer_toggle_set_active(GTK_CELL_RENDERER_TOGGLE(renderer), True);
gtk_tree_view_append_column (GTK_TREE_VIEW (TempWidget), column);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
g_signal_connect (renderer, 'toggled',
G_CALLBACK (@gtk_clb_toggle),
Sender);
g_signal_connect (TempWidget, 'row_activated',
G_CALLBACK (@gtk_clb_toggle_row_activated),
Sender);
TempInt := 1;
end;
renderer := gtk_cell_renderer_text_new();
column := gtk_tree_view_column_new_with_attributes ('LISTITEMS', renderer, ['text', TempInt, nil]);
gtk_tree_view_append_column (GTK_TREE_VIEW (TempWidget), column);
gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW (TempWidget), False);
gtk_container_add(GTK_CONTAINER(p), TempWidget);
gtk_widget_show(TempWidget);
SetMainWidget(p, TempWidget);
GetWidgetInfo(p, True)^.CoreWidget := TempWidget;
if Sender is TCustomListBox then
SetSelectionMode(Sender,p,TCustomListBox(Sender).MultiSelect,
TCustomListBox(Sender).ExtendedSelect);
end;
csMemo :
begin
P := gtk_scrolled_window_new(nil, nil);
TempWidget := gtk_text_view_new();
gtk_container_add(p, TempWidget);
GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.hscrollbar, GTK_CAN_FOCUS);
GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.vscrollbar, GTK_CAN_FOCUS);
gtk_scrolled_window_set_policy(PGtkScrolledWindow(p),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_shadow_type(PGtkScrolledWindow(p),GTK_SHADOW_IN);
SetMainWidget(p, TempWidget);
GetWidgetInfo(p, True)^.CoreWidget := TempWidget;
gtk_text_view_set_editable (PGtkTextView(TempWidget), not TCustomMemo(Sender).ReadOnly);
if TCustomMemo(Sender).WordWrap then
gtk_text_view_set_wrap_mode(PGtkTextView(TempWidget), GTK_WRAP_WORD)
else
gtk_text_view_set_wrap_mode(PGtkTextView(TempWidget), GTK_WRAP_NONE);
gtk_widget_show_all(P);
SetupProps:= true;
end;
else begin
StrDispose(StrTemp);
Result:=Inherited CreateComponent(Sender);
Exit;
end;
end; //end case
StrDispose(StrTemp);
FinishComponentCreate(Sender, P, SetupProps);
Result := THandle(P);
end;
function TGtk2WidgetSet.GetText(Sender: TComponent; var Text: String): Boolean;
var
CS: PChar;
Widget : PGtkWidget;
aTextBuffer : PGtkTextBuffer;
aTextIter1 : TGtkTextIter;
aTextIter2 : TGtkTextIter;
begin
Result := True;
case TControl(Sender).fCompStyle of
csEdit: begin
Widget:= GTK_WIDGET(Pointer(TWinControl(Sender).Handle));
CS := gtk_editable_get_chars(GTK_EDITABLE(Widget), 0, -1);
Text := StrPas(CS);
g_free(CS);
end;
csMemo : begin
Widget:= GetWidgetInfo(Pointer(TWinControl(Sender).Handle), True)^.CoreWidget;
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
gtk_text_buffer_get_bounds(aTextBuffer, @aTextIter1, @aTextIter2);
CS := gtk_text_buffer_get_text(aTextBuffer, @aTextIter1, @aTextIter2, True);
Text := StrPas(CS);
g_free(CS);
end;
else
Result := inherited GetText(Sender, Text);
end;
end;
procedure Tgtk2widgetset.HookSignals(const AGTKObject: PGTKObject; const ALCLObject: TObject);
begin
if (ALCLObject is TWinControl) then
Begin
inherited HookSignals(AGTKObject,ALCLObject);
End;
if (ALCLObject is TControl) then
Begin
case TControl(ALCLObject).FCompStyle of
csEdit:
begin
SetCallback(LM_CHANGED, AGTKObject, ALCLObject);
SetCallback(LM_ACTIVATE, AGTKObject,ALCLObject);
SetCallback(LM_CUTTOCLIP, AGTKObject,ALCLObject);
SetCallback(LM_COPYTOCLIP, AGTKObject,ALCLObject);
SetCallback(LM_PASTEFROMCLIP, AGTKObject,ALCLObject);
end;
csMemo:
begin
// SetCallback(LM_CHANGED, AGTKObject,ALCLObject);
//SetCallback(LM_ACTIVATE, AGTKObject,ALCLObject);
SetCallback(LM_CUTTOCLIP, AGTKObject,ALCLObject);
SetCallback(LM_COPYTOCLIP, AGTKObject,ALCLObject);
SetCallback(LM_PASTEFROMCLIP, AGTKObject,ALCLObject);
//SetCallback(LM_INSERTTEXT, AGTKObject,ALCLObject);
end;
end; //case
end
else
If (ALCLObject is TMenuItem) then
Begin
SetCallback(LM_ACTIVATE,AGTKObject,ALCLObject);
end;
end;
{------------------------------------------------------------------------------
Method: TGtk2WidgetSet.IntSendMessage3
Params: LM_Message - message to be processed by GTK2
Sender - sending control
data - pointer to (optional)
Returns: depends on the message and the sender
Processes messages from different components.
WARNING: the result of this function sometimes is not always really an
integer!!!!!
------------------------------------------------------------------------------}
function TGtk2WidgetSet.IntSendMessage3(LM_Message : Integer; Sender : TObject;
data : pointer) : integer;
var
handle : hwnd; // handle of sender
pStr : PChar; // temporary string pointer, must be allocated/disposed when used!
Widget : PGtkWidget; // pointer to gtk-widget (local use when neccessary)
ChildWidget : PGtkWidget; // generic pointer to a child gtk-widget (local use when neccessary)
aTextIter1 : TGtkTextIter;
aTextIter2 : TGtkTextIter;
aTextBuffer : PGtkTextBuffer;
aTreeSelect : PGtkTreeSelection;
aTreeModel : PGtkTreeModel;
aTreeIter : TGtkTreeIter;
aTreePath : PGtkTreePath;
TempInt : Integer;
TempBool : Boolean;
list : pGList;
begin
Result := 0; //default value just in case nothing sets it
Assert(False, 'Trace:Message received');
if Sender <> nil then
Assert(False, Format('Trace: [TGtk2WidgetSet.IntSendMessage3] %s --> Sent LM_Message: $%x (%s); Data: %d', [Sender.ClassName, LM_Message, GetMessageName(LM_Message), Integer(data)]));
// The following case is now split into 2 separate parts:
// 1st part should contain all messages which don't need the "handle" variable
// 2nd part has to contain all parts which need the handle
// Reason for this split are performance issues since we need RTTI to
// retrieve the handle
{ case LM_Message of
else}
begin
handle := hwnd(ObjectToGtkObject(Sender));
Case LM_Message of
LM_CLB_GETCHECKED :
begin
Result := 0;
if Assigned(Data)
and (Sender is TControl)
and (TControl(Sender).fCompStyle = csCheckListBox)
then begin
{ Get the child in question of that index }
Widget := GetWidgetInfo(Pointer(Handle),True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model(GTK_TREE_VIEW(Widget));
if (aTreeModel <> nil) and
(gtk_tree_model_iter_nth_child(aTreeModel,@aTreeIter, nil, Integer(Data^)))
then begin
gtk_tree_model_get (aTreeModel, @aTreeIter, [0, @TempBool, -1]);
if TempBool then
result := 1;
end;
end;
end;
LM_CLB_SETCHECKED :
begin
if Assigned(Data)
and (Sender is TControl)
and (TControl(Sender).fCompStyle = csCheckListBox)
then begin
{ Get the child in question of that index }
Widget := GetWidgetInfo(Pointer(Handle),True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model(GTK_TREE_VIEW(Widget));
if (aTreeModel <> nil) and
(gtk_tree_model_iter_nth_child(aTreeModel,@aTreeIter, nil, Integer(Data^)))
then
gtk_list_store_set(GTK_LIST_STORE(aTreeModel), @aTreeIter, [0, TLMSetChecked(Data^).Checked, -1]);
end;
end;
LM_GETITEMINDEX :
begin
case TControl(Sender).fCompStyle of
csListBox, csCheckListBox:
begin
if Handle<>0 then begin
Result:= -1;
Widget := GetWidgetInfo(Pointer(Handle),True)^.CoreWidget;
aTreeSelect := gtk_tree_view_get_selection(GTK_TREE_VIEW(Widget));
{$IfNDef GTK2_2}
list := nil;
gtk_tree_selection_selected_foreach(aTreeSelect, TGtkTreeSelectionForeachFunc(@gtkTreeSelectionGetSelectedRows), @List);
{$Else}
list := gtk_tree_selection_get_selected_rows(aTreeSelect, aTreeModel);
{$EndIf}
if not Assigned(List) then begin
result := -1;
exit;
end;
List := g_list_last(List);
aTreePath := PGtkTreePath(List^.Data);
Result := gtk_tree_path_get_indices(aTreePath)[0];
List := g_list_first(List);
g_list_foreach (list, TGFunc(@gtk_tree_path_free), nil);
g_list_free (list);
end else
Result:=-1;
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
LM_GETITEMS :
begin
case TControl(Sender).fCompStyle of
csComboBox:
Result:=longint(gtk_object_get_data(PGtkObject(Handle),'LCLList'));
csCheckListBox, csListBox:
begin
if TControl(Sender).fCompStyle = csCheckListBox then
TempInt := 1
else
TempInt := 0;
Widget:= GetWidgetInfo(Pointer(Handle), True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model(GTK_TREE_VIEW(Widget));
Data:= TGtkListStoreStringList.Create(GTK_LIST_STORE(aTreeModel),
TempInt, TWinControl(Sender));
if Sender is TCustomListBox then
TGtkListStoreStringList(Data).Sorted:=TCustomListBox(Sender).Sorted;
Result:= Integer(Data);
end;
else
raise Exception.Create('Message LM_GETITEMS - Not implemented');
end;
end;
LM_GETSEL :
begin
Result := 0; { assume: nothing found }
if (Sender is TControl)
and Assigned (data)
then case TControl(Sender).fCompStyle of
csListBox, csCheckListBox:
begin
{ Get the child in question of that index }
Widget := GetWidgetInfo(Pointer(Handle),True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model(GTK_TREE_VIEW(Widget));
aTreeSelect := gtk_tree_view_get_selection(GTK_TREE_VIEW(Widget));
if (aTreeModel <> nil) and (aTreeSelect <> nil) and
(gtk_tree_model_iter_nth_child(aTreeModel,@aTreeIter, nil, Integer(Data^))) and
(gtk_tree_selection_iter_is_selected(aTreeSelect, @aTreeIter))
then
result := 1;
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
LM_GETSELSTART :
begin
if (Sender is TControl) then begin
case TControl(Sender).fCompStyle of
csMemo:
begin
Widget:= GetWidgetInfo(Pointer(Handle), true)^.CoreWidget;
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
gtk_text_buffer_get_selection_bounds(aTextBuffer, @aTextIter1, nil);
result := gtk_text_iter_get_offset(@aTextIter1);
end;
csEdit:
begin
Widget:= GTK_WIDGET(Pointer(Handle));
if not gtk_editable_get_selection_bounds(GTK_EDITABLE(Widget),@result, nil) then
result := gtk_editable_get_position(GTK_EDITABLE(Widget));
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end
end
else
Result:= 0;
end;
LM_GETSELCOUNT :
begin
case (Sender as TControl).fCompStyle of
csListBox, csCheckListBox :
begin
Widget := GetWidgetInfo(Pointer(Handle),True)^.CoreWidget;
aTreeSelect := gtk_tree_view_get_selection(GTK_TREE_VIEW(Widget));
{$IfNDef GTK2_2}
Result := 0;
gtk_tree_selection_selected_foreach(aTreeSelect, TGtkTreeSelectionForeachFunc(@gtkTreeSelectionCountSelectedRows), @Result);
{$Else}
Result := gtk_tree_selection_count_selected_rows(aTreeSelect);
{$EndIf}
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
LM_GETSELLEN :
begin
if (Sender is TControl) then begin
case TControl(Sender).fCompStyle of
csMemo:
begin
Widget:= GetWidgetInfo(Pointer(Handle), true)^.CoreWidget;
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
gtk_text_buffer_get_selection_bounds(aTextBuffer, @aTextIter1, @aTextIter2);
result:= Abs(gtk_text_iter_get_offset(@aTextIter2) - gtk_text_iter_get_offset(@aTextIter1));
end;
csEdit:
begin
Widget:= GTK_WIDGET(Pointer(Handle));
if gtk_editable_get_selection_bounds(GTK_EDITABLE(Widget),@result, @TempInt) then
result := TempInt - Result
else
result := 0;
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
end;
LM_SETBORDER:
begin
if (Sender is TWinControl) then
begin
if (TControl(Sender).fCompStyle in [csListBox, csCListBox, csCheckListBox]) then
begin
Widget:= PGtkWidget(TWinControl(Sender).Handle);
if TListBox(Sender).BorderStyle = TBorderStyle(bsSingle)
then
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(Widget), GTK_SHADOW_IN)
else
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(Widget), GTK_SHADOW_NONE);
end
end;
end;
LM_SETITEMINDEX:
if Handle<>0 then begin
case TControl(Sender).fCompStyle of
csListBox, csCheckListBox:
begin
Widget := GetWidgetInfo(Pointer(Handle), True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model(GTK_TREE_VIEW(Widget));
aTreeSelect := gtk_tree_view_get_selection(GTK_TREE_VIEW(Widget));
if (aTreeModel <> nil) and (aTreeSelect <> nil) then begin
if (Integer(Data)>=0) and
(gtk_tree_model_iter_nth_child(aTreeModel,@aTreeIter, nil, Integer(Data)))
then
gtk_tree_selection_select_iter(aTreeSelect, @aTreeIter)
else
gtk_tree_selection_unselect_all(aTreeSelect);
end;
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
LM_SETSEL:
begin
if (Sender is TControl)
and Assigned (data)
then case TControl(Sender).fCompStyle of
csListBox, csCheckListBox:
begin
Widget := GetWidgetInfo(Pointer(Handle), True)^.CoreWidget;
aTreeModel := gtk_tree_view_get_model(GTK_TREE_VIEW(Widget));
aTreeSelect := gtk_tree_view_get_selection(GTK_TREE_VIEW(Widget));
if (aTreeModel <> nil) and (aTreeSelect <> nil) and
(gtk_tree_model_iter_nth_child(aTreeModel,@aTreeIter, nil, TLMSetSel(Data^).Index))
then
if TLMSetSel(Data^).Selected then
gtk_tree_selection_select_iter(aTreeSelect, @aTreeIter)
else
if gtk_tree_selection_iter_is_selected(aTreeSelect, @aTreeIter) then
gtk_tree_selection_unselect_iter(aTreeSelect, @aTreeIter);
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
LM_SETSELSTART:
begin
if (Sender is TControl) then begin
case TControl(Sender).fCompStyle of
csMemo:
begin
Widget:= GetWidgetInfo(Pointer(Handle), true)^.CoreWidget;
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
Debugln('TODO(GTK2): IntSendMessage3, LM_SETSELSTART, csMemo');
{gtk_text_buffer_get_selection_bounds(aTextBuffer, @aTextIter1, nil);
result := gtk_text_iter_get_offset(@aTextIter1);}
end;
csEdit:
begin
Widget:= GTK_WIDGET(Pointer(Handle));
if gtk_editable_get_selection_bounds(GTK_EDITABLE(Widget),nil, @TempInt) then
If (Integer(Data) >= 0) and (Integer(Data)<=TempInt) then
gtk_editable_select_region(GTK_EDITABLE(Widget), Integer(Data), TempInt+1);
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end
else
Result:= 0;
end;
LM_SETSELLEN :
begin
if (Sender is TControl) then begin
case TControl(Sender).fCompStyle of
csMemo:
begin
Widget:= GetWidgetInfo(Pointer(Handle), true)^.CoreWidget;
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
Debugln('TODO(GTK2): IntSendMessage3, LM_SETSELLEN, csMemo');
{gtk_text_buffer_get_selection_bounds(aTextBuffer, @aTextIter1, @aTextIter2);
result:= Abs(gtk_text_iter_get_offset(@aTextIter2) - gtk_text_iter_get_offset(@aTextIter1));}
end;
csEdit:
begin
Widget:= GTK_WIDGET(Pointer(Handle));
if gtk_editable_get_selection_bounds(GTK_EDITABLE(Widget),@TempInt, nil) then
gtk_editable_select_region(GTK_EDITABLE(Widget), TempInt, TempInt+Integer(Data)+1)
else
gtk_editable_select_region(GTK_EDITABLE(Widget), gtk_editable_get_position(GTK_EDITABLE(Widget)),
gtk_editable_get_position(GTK_EDITABLE(Widget)) + Integer(Data)+1)
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end;
end;
end;
LM_SORT:
begin
if (Sender is TControl) and assigned (data) then
begin
case TControl(Sender).fCompStyle of
csListBox,
csCheckListBox
: TGtkListStoreStringList(TLMSort(Data^).List).Sorted:=
TLMSort(Data^).IsSorted;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end;
end
end
end;
else begin
result := inherited IntSendMessage3(LM_Message, Sender, data);
exit;
end; // end of else-part of 2nd case
end; // end of 2nd case
end; // end of else-part of 1st case
// end; // end of 1st case
end;
{------------------------------------------------------------------------------
Function: TGtk2WidgetSet.SetCallback
Params: Msg - message for which to set a callback
sender - object to which callback will be send
Returns: nothing
Applies a Message to the sender
------------------------------------------------------------------------------}
procedure TGTK2WidgetSet.SetCallback(const AMsg: LongInt; const AGTKObject: PGTKObject; const ALCLObject: TObject);
procedure ConnectSenderSignal(const AnObject:PGTKObject; const ASignal: PChar;
const ACallBackProc: Pointer);
begin
ConnectSignal(AnObject,ASignal,ACallBackProc,TComponent(ALCLObject));
end;
procedure ConnectSenderSignalAfter(const AnObject:PGTKObject;
const ASignal: PChar; const ACallBackProc: Pointer);
begin
ConnectSignalAfter(AnObject,ASignal,ACallBackProc,TComponent(ALCLObject));
end;
procedure ConnectSenderSignal(const AnObject:PGTKObject; const ASignal: PChar;
const ACallBackProc: Pointer; const ReqSignalMask: TGdkEventMask);
begin
ConnectSignal(AnObject,ASignal,ACallBackProc,ALCLObject,
ReqSignalMask);
end;
procedure ConnectSenderSignalAfter(const AnObject:PGTKObject;
const ASignal: PChar; const ACallBackProc: Pointer;
const ReqSignalMask: TGdkEventMask);
begin
ConnectSignalAfter(AnObject,ASignal,ACallBackProc,ALCLObject,
ReqSignalMask);
end;
procedure ConnectFocusEvents(const AnObject: PGTKObject);
begin
ConnectSenderSignal(AnObject, 'focus-in-event', @gtk2FocusCB);
ConnectSenderSignalAfter(AnObject, 'focus-in-event', @gtk2FocusCBAfter);
ConnectSenderSignal(AnObject, 'focus-out-event', @gtk2KillFocusCB);
ConnectSenderSignalAfter(AnObject, 'focus-out-event', @gtk2KillFocusCBAfter);
end;
procedure ConnectKeyPressReleaseEvents(const AnObject: PGTKObject);
begin
ConnectSenderSignal(AnObject,
'key-press-event', @GTK2KeyUpDown, GDK_KEY_PRESS_MASK);
//ConnectSenderSignalAfter(AnObject,
// 'key-press-event', @GTK2KeyUpDownAfter, GDK_KEY_PRESS_MASK);
ConnectSenderSignal(AnObject,
'key-release-event', @GTK2KeyUpDown, GDK_KEY_RELEASE_MASK);
//ConnectSenderSignalAfter(AnObject,
// 'key-release-event', @GTK2KeyUpDownAfter, GDK_KEY_RELEASE_MASK);
end;
var
gObject, gFixed, gCore, Scroll: PGTKObject;
begin
gObject := AGTKObject;
if gObject = nil then Exit;
// gFixed is the widget with the client area (e.g. TGroupBox, TForm have this)
gFixed := PGTKObject(GetFixedWidget(gObject));
if gFixed = nil then gFixed := gObject;
// gCore is the main widget (e.g. TListView has this)
gCore:= PGtkObject(GetWidgetInfo(gObject, True)^.CoreWidget);
case AMsg of
LM_FOCUS :
begin
if (ALCLObject is TCustomComboBox) then begin
ConnectFocusEvents(PgtkObject(PgtkCombo(gObject)^.entry));
ConnectFocusEvents(PgtkObject(PgtkCombo(gObject)^.list));
end else begin
ConnectFocusEvents(gCore);
end;
end;
LM_CHAR,
LM_KEYDOWN,
LM_KEYUP,
LM_SYSCHAR,
LM_SYSKEYDOWN,
LM_SYSKEYUP:
begin
if (ALCLObject is TCustomComboBox) then begin
ConnectKeyPressReleaseEvents(PgtkObject(PgtkCombo(gObject)^.entry));
end
else if (ALCLObject is TCustomForm) then begin
ConnectKeyPressReleaseEvents(gObject);
end;
ConnectKeyPressReleaseEvents(gCore);
end;
LM_SHOWWINDOW :
begin
ConnectSenderSignal(gObject, 'show', @gtk2showCB);
ConnectSenderSignal(gObject, 'hide', @gtk2hideCB);
end;
else
Inherited SetCallback(AMsg, AGTKObject, ALCLObject);
end;
end;
Function TGtk2WidgetSet.LoadStockPixmap(StockID: longint) : HBitmap;
var
Pixmap : PGDIObject;
StockName : PChar;
IconSet : PGtkIconSet;
Pixbuf : PGDKPixbuf;
begin
Case StockID Of
idButtonOk : StockName := GTK_STOCK_OK;
idButtonCancel : StockName := GTK_STOCK_CANCEL;
idButtonYes : StockName := GTK_STOCK_YES;
idButtonNo : StockName := GTK_STOCK_NO;
idButtonHelp : StockName := GTK_STOCK_HELP;
idButtonAbort : StockName := GTK_STOCK_CANCEL;
idButtonClose : StockName := GTK_STOCK_QUIT;
idDialogWarning : StockName := GTK_STOCK_DIALOG_WARNING;
idDialogError : StockName := GTK_STOCK_DIALOG_ERROR;
idDialogInfo : StockName := GTK_STOCK_DIALOG_INFO;
idDialogConfirm : StockName := GTK_STOCK_DIALOG_QUESTION;
else begin
Result := inherited LoadStockPixmap(StockID);
exit;
end;
end;
if (StockID >= idButtonBase) and (StockID <= idDialogBase) then
IconSet := gtk_style_lookup_icon_set(GetStyle(lgsButton), StockName)
else
IconSet := gtk_style_lookup_icon_set(GetStyle(lgsWindow), StockName);
If (IconSet = nil) then begin
Result := inherited LoadStockPixmap(StockID);
exit;
end;
if (StockID >= idButtonBase) and (StockID <= idDialogBase) then
pixbuf := gtk_icon_set_render_icon(IconSet, GetStyle(lgsbutton), GTK_TEXT_DIR_NONE, GTK_STATE_NORMAL, GTK_ICON_SIZE_BUTTON, GetStyleWidget(lgsbutton), nil)
else
pixbuf := gtk_icon_set_render_icon(IconSet, GetStyle(lgswindow), GTK_TEXT_DIR_NONE, GTK_STATE_NORMAL, GTK_ICON_SIZE_DIALOG, GetStyleWidget(lgswindow), nil);
Pixmap := NewGDIObject(gdiBitmap);
With Pixmap^ do begin
GDIBitmapType := gbPixmap;
visual := gdk_visual_get_system();
gdk_visual_ref(visual);
colormap := gdk_colormap_get_system();
gdk_colormap_ref(colormap);
gdk_pixbuf_render_pixmap_and_mask(pixbuf, GDIPixmapObject, GDIBitmapMaskObject, 128);
end;
gdk_pixbuf_unref(pixbuf);
Result := HBitmap(Pixmap);
end;
{------------------------------------------------------------------------------
Method: TGtk2WidgetSet.SetLabel
Params: sender - the calling object
data - String (PChar) to be set as label for a control
Returns: Nothing
Sets the label text on a widget
------------------------------------------------------------------------------}
procedure TGtk2WidgetSet.SetLabel(Sender : TObject; Data : Pointer);
var
Widget : PGtkWidget;
aTextBuffer : PGtkTextBuffer;
aTextIter1 : TGtkTextIter;
aTextIter2 : TGtkTextIter;
DC : hDC;
aLabel, pLabel: pchar;
AccelKey : integer;
begin
if Sender is TMenuItem then begin
inherited SetLabel(Sender, Data);
exit;
end;
if Sender is TWinControl
then Assert(False, Format('Trace: [TGtk2WidgetSet.SetLabel] %s --> label %s', [Sender.ClassName, TControl(Sender).Caption]))
else begin
Assert(False, Format('Trace:WARNING: [TGtk2WidgetSet.SetLabel] %s --> No Decendant of TWinControl', [Sender.ClassName]));
RaiseException('[TGtk2WidgetSet.SetLabel] ERROR: Sender ('+Sender.Classname+')'
+' is not TWinControl ');
end;
Widget := PGtkWidget(TWinControl(Sender).Handle);
Assert(Widget = nil, 'Trace:WARNING: [TGtk2WidgetSet.SetLabel] --> got nil pointer');
Assert(False, 'Trace:Setting Str1 in SetLabel');
pLabel := pchar(Data);
case TControl(Sender).fCompStyle of
csEdit : begin
gtk_entry_set_text(pGtkEntry(Widget), pLabel);
{LockOnChange(PGtkObject(Widget),+1);
gtk_editable_delete_text(pGtkEditable(P), 0, -1);
gtk_editable_insert_text(pGtkEditable(P), pLabel, StrLen(pLabel). 0);
LockOnChange(PGtkObject(Widget),-1);}
end;
csLabel:
begin
gtk_label_set_use_underline(PGtkLabel(Widget), True);
if TLabel(Sender).ShowAccelChar then begin
If TLabel(sender).WordWrap and (TLabel(Sender).Caption<>'') then begin
DC := GetDC(TLabel(Sender).Handle);
aLabel := ForceLineBreaks(DC, pLabel, TLabel(Sender).Width, True);
DeleteDC(DC);
end
else
aLabel:= Ampersands2Underscore(pLabel);
try
gtk_label_set_label(pGtkLabel(Widget), aLabel);
AccelKey:= gtk_label_get_mnemonic_keyval(pGtkLabel(Widget));
Accelerate(TComponent(Sender),Widget,AccelKey,0,'grab_focus');
finally
StrDispose(aLabel);
end;
end else begin
If TLabel(sender).WordWrap then begin
DC := GetDC(TLabel(Sender).Handle);
aLabel := ForceLineBreaks(DC, pLabel, TLabel(Sender).Width, False);
gtk_label_set_label(PGtkLabel(Widget), aLabel);
StrDispose(aLabel);
DeleteDC(DC);
end
else
gtk_label_set_label(PGtkLabel(Widget), pLabel);
end;
end;
csMemo : begin
Widget:= PGtkWidget(GetWidgetInfo(Widget, True)^.CoreWidget);
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(Widget));
gtk_text_buffer_begin_user_action(aTextBuffer);
gtk_text_buffer_get_bounds(aTextBuffer, @aTextIter1, @aTextIter2);
gtk_text_buffer_delete(aTextBuffer, @aTextIter1, @aTextIter2);
gtk_text_buffer_get_bounds(aTextBuffer, @aTextIter1, @aTextIter2);
gtk_text_buffer_insert(aTextBuffer, @aTextIter1, pLabel, StrLen(pLabel));
gtk_text_buffer_end_user_action(aTextBuffer);
end;
else
inherited SetLabel(Sender, Data);
end;
Assert(False, Format('trace: [TGtk2WidgetSet.SetLabel] %s --> END', [Sender.ClassName]));
end;
{------------------------------------------------------------------------------
Method: TGtk2WidgetSet.SetProperties
Params: Sender : the lcl object which called this func via SenMessage
Returns: currently always 0
Depending on the compStyle, this function will apply all properties of
the calling object to the corresponding GTK2 object.
------------------------------------------------------------------------------}
function TGtk2WidgetSet.SetProperties(Sender : TObject) : integer;
const
cLabelAlignX : array[TAlignment] of gfloat = (0.0, 1.0, 0.5);
cLabelAlignY : array[TTextLayout] of gfloat = (0.0, 0.5, 1.0);
cLabelAlign : array[TAlignment] of TGtkJustification = (GTK_JUSTIFY_LEFT, GTK_JUSTIFY_RIGHT, GTK_JUSTIFY_CENTER);
var
wHandle : Pointer;
Widget, ImplWidget : PGtkWidget;
i : Longint;
aTextBuffer : PGtkTextBuffer;
aTextIter1 : TGtkTextIter;
aTextIter2 : TGtkTextIter;
begin
Result := 0; // default if nobody sets it
if Sender is TWinControl
then
Assert(False, Format('Trace: [TGtk2WidgetSet.SetProperties] %s', [Sender.ClassName]))
else
RaiseException('TGtk2WidgetSet.SetProperties: '
+' Sender.ClassName='+Sender.ClassName);
wHandle:= Pointer(TWinControl(Sender).Handle);
Widget:= GTK_WIDGET(wHandle);
case TControl(Sender).fCompStyle of
csEdit :
with TCustomEdit(Sender) do
begin
gtk_editable_set_editable(GTK_ENTRY(wHandle), not (TCustomEdit(Sender).ReadOnly));
gtk_entry_set_max_length(GTK_ENTRY(wHandle), TCustomEdit(Sender).MaxLength);
gtk_entry_set_visibility(GTK_ENTRY(wHandle), (TCustomEdit(Sender).EchoMode = emNormal) and (TCustomEdit(Sender).PassWordChar=#0));
if (TCustomEdit(Sender).EchoMode = emNone) then
gtk_entry_set_invisible_char(GTK_ENTRY(wHandle), 0)
else
gtk_entry_set_invisible_char(GTK_ENTRY(wHandle), Longint(TCustomEdit(Sender).PassWordChar));
end;
csLabel :
with TLabel(Sender) do
begin
gtk_label_set_line_wrap(GTK_LABEL(wHandle), False);
gtk_misc_set_alignment(GTK_MISC(wHandle), cLabelAlignX[Alignment],
0.0);
gtk_label_set_line_wrap(GTK_LABEL(wHandle), TRUE);
gtk_label_set_justify(GTK_LABEL(wHandle), cLabelAlign[Alignment]);
end;
csMemo:
begin
ImplWidget:= GetWidgetInfo(wHandle, true)^.CoreWidget;
gtk_text_view_set_editable (PGtkTextView(ImplWidget), not TCustomMemo(Sender).ReadOnly);
if TCustomMemo(Sender).WordWrap then
gtk_text_view_set_wrap_mode(PGtkTextView(ImplWidget), GTK_WRAP_WORD)
else
gtk_text_view_set_wrap_mode(PGtkTextView(ImplWidget), GTK_WRAP_NONE);
case (Sender as TCustomMemo).Scrollbars of
ssHorizontal: gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
ssVertical: gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
ssBoth: gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
ssAutoHorizontal: gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
ssAutoVertical: gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
ssAutoBoth: gtk_scrolled_window_set_policy(
GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
else
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(wHandle),
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
end;
If (TCustomMemo(Sender).MaxLength >= 0) then begin
aTextBuffer := gtk_text_view_get_buffer(GTK_TEXT_VIEW(ImplWidget));
i:= gtk_text_buffer_get_char_count(aTextBuffer);
if i > TCustomMemo(Sender).MaxLength then begin
gtk_text_buffer_get_bounds(aTextBuffer, nil, @aTextIter2);
gtk_text_buffer_get_iter_at_offset(aTextBuffer, @aTextIter1, i);
gtk_text_buffer_delete(aTextBuffer, @aTextIter1, @aTextIter2);
end;
end;
end;
else
Result := inherited SetProperties(Sender);
end;
end;
{------------------------------------------------------------------------------
procedure TGtk2WidgetSet.SetSelectionMode(Sender: TObject; Widget: PGtkWidget;
MultiSelect, ExtendedSelect: boolean);
------------------------------------------------------------------------------}
procedure TGtk2WidgetSet.SetSelectionMode(Sender: TObject; Widget: PGtkWidget;
MultiSelect, ExtendedSelect: boolean);
var
AControl: TWinControl;
SelectionMode: TGtkSelectionMode;
Selection : PGtkTreeSelection;
begin
AControl:=TWinControl(Sender);
if (AControl is TWinControl) and
(AControl.fCompStyle in [csListBox, csCheckListBox, csCListBox]) then
begin
if MultiSelect then
SelectionMode:= GTK_SELECTION_MULTIPLE
else
SelectionMode:= GTK_SELECTION_SINGLE;
case AControl.fCompStyle of
csListBox, csCheckListBox:
begin
Selection := gtk_tree_view_get_selection(GTK_TREE_VIEW(
GetWidgetInfo(Widget, True)^.CoreWidget));
gtk_tree_selection_set_mode(Selection, SelectionMode);
end;
else
inherited SetSelectionMode(Sender, Widget, MultiSelect, ExtendedSelect);
end;
end;
end;
{------------------------------------------------------------------------------
function TGtk2WidgetSet.SetTopIndex(Sender: TObject; NewTopIndex: integer
): integer;
------------------------------------------------------------------------------}
function TGtk2WidgetSet.SetTopIndex(Sender: TObject; NewTopIndex: integer
): integer;
var
aTreeView: PGtkTreeView;
aTreeModel : PGtkTreeModel;
aTreeColumn : PGtkTreeViewColumn;
aTreeIter : TGtkTreeIter;
aTreePath : PGtkTreePath;
Count : Integer;
begin
Result:=0;
if not (Sender is TWinControl) then exit;
case TWinControl(Sender).fCompStyle of
csListBox, csCheckListBox:
begin
aTreeView := GTK_TREE_VIEW(GetWidgetInfo(Pointer(TWinControl(Sender).Handle), True)^.CoreWidget);
aTreeModel := gtk_tree_view_get_model(aTreeView);
If NewTopIndex < 0 then
NewTopIndex := 0
else begin
Count := gtk_tree_model_iter_n_children(aTreeModel,nil);
If NewTopIndex >= Count then
NewTopIndex := Count - 1;
end;
if gtk_tree_model_iter_nth_child(aTreeModel,@aTreeIter, nil, NewTopIndex) then begin
aTreePath := gtk_tree_model_get_path(aTreeModel, @aTreeIter);
aTreeColumn := gtk_tree_view_get_column(aTreeView, 0);
gtk_tree_view_scroll_to_cell(aTreeView, aTreePath, aTreeColumn, False, 0.0, 0.0);
gtk_tree_path_free(aTreePath);
end;
end;
end;
end;
{------------------------------------------------------------------------------
procedure TGtk2WidgetSet.UpdateDCTextMetric(DC: TDeviceContext);
------------------------------------------------------------------------------}
procedure TGtk2WidgetSet.UpdateDCTextMetric(DC: TDeviceContext);
const
TestString = '{Am|g_}';
var
XT : TSize;
dummy: LongInt;
UseFontDesc : PPangoFontDescription;
UnRef : Boolean;
AVGBuffer: array[#32..#126] of char;
AvgLen: integer;
c: char;
Underline,
StrikeOut : Boolean;
Layout : PPangoLayout;
AttrList : PPangoAttrList;
Attr : PPangoAttribute;
Extents : TPangoRectangle;
begin
with TDeviceContext(DC) do begin
if dcfTextMetricsValid in DCFlags then begin
// cache valid
end else begin
if (CurrentFont = nil) or (CurrentFont^.GDIFontObject = nil)
then begin
UseFontDesc := GetDefaultFontDesc(true);
UnRef := True;
Underline := False;
StrikeOut := False;
end
else begin
UseFontDesc := CurrentFont^.GDIFontObject;
UnRef := False;
Underline := CurrentFont^.Underline;
StrikeOut := CurrentFont^.StrikeOut;
end;
If UseFontDesc = nil then
DebugLn('WARNING: [TGtk2WidgetSet.GetTextMetrics] Missing font')
else begin
Layout := gtk_widget_create_pango_layout (GetStyleWidget(lgsdefault), nil);
pango_layout_set_font_description(Layout, UseFontDesc);
AttrList := pango_layout_get_attributes(Layout);
If (AttrList = nil) then
AttrList := pango_attr_list_new();
//fix me... what about &&, can we strip and do do markup substitution?
If Underline then
Attr := pango_attr_underline_new(PANGO_UNDERLINE_SINGLE)
else
Attr := pango_attr_underline_new(PANGO_UNDERLINE_NONE);
pango_attr_list_change(AttrList,Attr);
Attr := pango_attr_strikethrough_new(StrikeOut);
pango_attr_list_change(AttrList,Attr);
pango_layout_set_attributes(Layout, AttrList);
pango_layout_set_single_paragraph_mode(Layout, TRUE);
pango_layout_set_width(Layout, -1);
pango_layout_set_alignment(Layout, PANGO_ALIGN_LEFT);
//fix me... and what about UTF-8 conversion?
//this could be a massive problem since we
//will need to know before hand what the current
//locale is, and if we stored UTF-8 string this would break
//cross-compatibility with GTK1.2 and win32 interfaces.....
pango_layout_set_text(Layout, TestString, length(TestString));
pango_layout_get_extents(Layout, nil, @Extents);
g_object_unref(Layout);
If UnRef then
pango_font_description_free(UseFontDesc);
FillChar(DCTextMetric, SizeOf(DCTextMetric), 0);
with DCTextMetric do begin
IsDoubleByteChar:=False;//FontIsDoubleByteCharsFont(UseFont);
for c:=Low(AVGBuffer) to High(AVGBuffer) do
AVGBuffer[c]:=c;
lbearing := PANGO_LBEARING(extents) div PANGO_SCALE;
rBearing := PANGO_RBEARING(extents) div PANGO_SCALE;
TextMetric.tmAscent := PANGO_ASCENT(extents) div PANGO_SCALE;
TextMetric.tmDescent := PANGO_DESCENT(extents) div PANGO_SCALE;
AvgLen:=ord(High(AVGBuffer))-ord(Low(AVGBuffer))+1;
GetTextExtentPoint(HDC(DC), @AVGBuffer[Low(AVGBuffer)],
AvgLen, XT);
if not IsDoubleByteChar then
XT.cX := XT.cX div AvgLen
else
// Quick hack for double byte char fonts
XT.cX := XT.cX div (AvgLen div 2);
TextMetric.tmHeight := XT.cY;
TextMetric.tmAscent := TextMetric.tmHeight - TextMetric.tmDescent;
TextMetric.tmAveCharWidth := XT.cX;
if TextMetric.tmAveCharWidth<1 then TextMetric.tmAveCharWidth:=1;
{temp EVIL hack FIXME -->}
AVGBuffer[Low(AVGBuffer)]:='M';
GetTextExtentPoint(HDC(DC), @AVGBuffer[Low(AVGBuffer)],
1, XT);
TextMetric.tmMaxCharWidth := XT.cX;
AVGBuffer[Low(AVGBuffer)]:='W';
GetTextExtentPoint(HDC(DC), @AVGBuffer[Low(AVGBuffer)],
1, XT);
TextMetric.tmMaxCharWidth := Max(TextMetric.tmMaxCharWidth,XT.cX);
{<-- temp EVIL hack FIXME}
if TextMetric.tmMaxCharWidth<1 then
TextMetric.tmMaxCharWidth:=1;
end;
end;
Include(DCFlags,dcfTextMetricsValid);
end;
end;
end;
{$IFDEF ASSERT_IS_ON}
{$UNDEF ASSERT_IS_ON}
{$C-}
{$ENDIF}
{ =============================================================================
$Log$
Revision 1.12 2004/05/22 14:35:33 mattias
fixed button return key
Revision 1.11 2004/05/11 09:49:47 mattias
started sending CN_KEYUP
Revision 1.10 2004/04/13 14:03:29 marc
Patch from Ladislav Michl
Revision 1.9 2004/03/09 15:30:15 peter
* fixed gtk2 compilation
Revision 1.8 2004/03/05 00:41:15 marc
* Renamed TGtk2Object to TGtk2WidgetSet
Revision 1.7 2004/01/04 16:44:33 mattias
updated gtk2 package
Revision 1.6 2003/10/04 00:36:30 ajgenius
partly fix csLabel for GTK2, Layout is still wacked.
Revision 1.5 2003/10/03 01:25:01 ajgenius
add more gtk1i<->gtk2 key & event wrappers,
move more GTK2 workarounds from gtk to gtk2 interface,
start GTK2 interface SetCallback
Revision 1.4 2003/10/02 18:15:44 ajgenius
more gtk2 (check)ListBox implementation
Revision 1.3 2003/10/02 01:18:38 ajgenius
more callbacks fixes for gtk2, partly fix gtk2 CheckListBox
Revision 1.2 2003/09/24 17:23:54 ajgenius
more work toward GTK2 - partly fix CheckListBox, & MenuItems
Revision 1.1 2003/09/22 20:08:56 ajgenius
break GTK2 object and winapi into includes like the GTK interface
}