1{ $Id$} 2{ 3 ***************************************************************************** 4 * Gtk2WSCheckLst.pp * 5 * ----------------- * 6 * * 7 * * 8 ***************************************************************************** 9 10 ***************************************************************************** 11 This file is part of the Lazarus Component Library (LCL) 12 13 See the file COPYING.modifiedLGPL.txt, included in this distribution, 14 for details about the license. 15 ***************************************************************************** 16} 17unit Gtk2WSCheckLst; 18 19{$mode objfpc}{$H+} 20 21interface 22 23uses 24 // RTL 25 SysUtils, Classes, 26 Gtk2, GLib2, Gtk2Def, 27 // LCL 28//////////////////////////////////////////////////// 29// I M P O R T A N T 30//////////////////////////////////////////////////// 31// To get as little as posible circles, 32// uncomment only when needed for registration 33//////////////////////////////////////////////////// 34 CheckLst, StdCtrls, Controls, LCLType, LMessages, LCLProc, 35//////////////////////////////////////////////////// 36 WSCheckLst, WSLCLClasses; 37 38type 39 40 { TGtk2WSCheckListBox } 41 42 { TGtk2WSCustomCheckListBox } 43 44 TGtk2WSCustomCheckListBox = class(TWSCustomCheckListBox) 45 private 46 class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual; 47 published 48 class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override; 49 class function GetItemEnabled(const ACheckListBox: TCustomCheckListBox; 50 const AIndex: integer): Boolean; override; 51 class function GetState(const ACheckListBox: TCustomCheckListBox; 52 const AIndex: integer): TCheckBoxState; override; 53 class procedure SetItemEnabled(const ACheckListBox: TCustomCheckListBox; 54 const AIndex: integer; const AEnabled: Boolean); override; 55 class procedure SetState(const ACheckListBox: TCustomCheckListBox; 56 const AIndex: integer; const AState: TCheckBoxState); override; 57 end; 58 59 60implementation 61 62uses 63 Gtk2WSControls, Gtk2Proc, Gtk2CellRenderer; 64 65const 66 gtk2CLBState = 0; // byte 67 gtk2CLBText = 1; // PGChar 68 gtk2CLBDisabled = 3; // gboolean 69 70{ TGtk2WSCheckListBox } 71 72function Gtk2WS_CheckListBoxSelectionChanged({%H-}Widget: PGtkWidget; 73 WidgetInfo: PWidgetInfo): gboolean; cdecl; 74var 75 Mess: TLMessage; 76begin 77 Result := False; 78 if WidgetInfo^.ChangeLock > 0 then 79 Exit; 80 FillChar(Mess{%H-},SizeOf(Mess),0); 81 Mess.msg := LM_SELCHANGE; 82 DeliverMessage(WidgetInfo^.LCLObject, Mess); 83end; 84 85procedure Gtk2WS_CheckListBoxDataFunc({%H-}tree_column: PGtkTreeViewColumn; 86 cell: PGtkCellRenderer; tree_model: PGtkTreeModel; iter: PGtkTreeIter; {%H-}data: Pointer); cdecl; 87var 88 b: byte; 89 ADisabled: gboolean; 90 AValue: TCheckBoxState; 91begin 92 gtk_tree_model_get(tree_model, iter, [gtk2CLBState, @b, -1]); 93 gtk_tree_model_get(tree_model, iter, [gtk2CLBDisabled, @ADisabled, -1]); 94 AValue := TCheckBoxState(b); // TCheckBoxState is 4 byte 95 g_object_set(cell, 'inconsistent', [gboolean(AValue = cbGrayed), nil]); 96 if AValue <> cbGrayed then 97 gtk_cell_renderer_toggle_set_active(PGtkCellRendererToggle(cell), AValue = cbChecked); 98 99 g_object_set(cell, 'activatable', [gboolean(not ADisabled), nil]); 100end; 101 102procedure Gtk2WS_CheckListBoxToggle({%H-}cellrenderertoggle : PGtkCellRendererToggle; 103 arg1 : PGChar; WidgetInfo: PWidgetInfo); cdecl; 104var 105 Mess: TLMessage; 106 Param: PtrInt; 107 Iter : TGtkTreeIter; 108 TreeView: PGtkTreeView; 109 ListStore: PGtkTreeModel; 110 Path: PGtkTreePath; 111 AState: TCheckBoxState; 112begin 113 {$IFDEF EventTrace} 114 EventTrace('Gtk2WS_CheckListBoxToggle', WidgetInfo^.LCLObject); 115 {$ENDIF} 116 Val(arg1, Param); 117 118 TreeView := PGtkTreeView(WidgetInfo^.CoreWidget); 119 ListStore := gtk_tree_view_get_model(TreeView); 120 121 if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, Param) then 122 begin 123 TCustomCheckListBox(WidgetInfo^.LCLObject).Toggle(Param); 124 AState:=TCustomCheckListBox(WidgetInfo^.LCLObject).State[Param]; 125 126 gtk_list_store_set(ListStore, @Iter, [gtk2CLBState, 127 Byte(AState), -1]); 128 end; 129 130 131 Path := gtk_tree_path_new_from_indices(Param, -1); 132 if Path <> nil then 133 begin 134 if TreeView^.priv^.tree <> nil then 135 gtk_tree_view_set_cursor(TreeView, Path, nil, False); 136 gtk_tree_path_free(Path); 137 end; 138 139 FillChar(Mess{%H-}, SizeOf(Mess), #0); 140 Mess.Msg := LM_CHANGED; 141 142 Mess.Result := 0; 143 Mess.WParam := Param; 144 DeliverMessage(widgetInfo^.lclObject, Mess); 145 146end; 147 148class procedure TGtk2WSCustomCheckListBox.SetCallbacks(const AGtkWidget: PGtkWidget; 149 const AWidgetInfo: PWidgetInfo); 150//var 151// Selection: PGtkTreeSelection; 152begin 153 TGtk2WSBaseScrollingWinControl.SetCallbacks(AGtkWidget,AWidgetInfo); 154 155 {Selection :=} gtk_tree_view_get_selection(PGtkTreeView(AWidgetInfo^.CoreWidget)); 156 //SignalConnect(PGtkWidget(Selection), 'changed', @Gtk2WS_ListBoxChange, AWidgetInfo); 157end; 158 159class function TGtk2WSCustomCheckListBox.CreateHandle( 160 const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; 161var 162 TreeViewWidget: PGtkWidget; 163 p: PGtkWidget; // ptr to the newly created GtkWidget 164 liststore : PGtkListStore; 165 Selection: PGtkTreeSelection; 166 renderer : PGtkCellRenderer; 167 column : PGtkTreeViewColumn; 168 WidgetInfo: PWidgetInfo; 169begin 170 Result := TGtk2WSBaseScrollingWinControl.CreateHandle(AWinControl,AParams); 171 p := {%H-}PGtkWidget(Result); 172 173 if Result = 0 then exit; 174 175 WidgetInfo := GetWidgetInfo(p); 176 177 GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.hscrollbar, GTK_CAN_FOCUS); 178 GTK_WIDGET_UNSET_FLAGS(PGtkScrolledWindow(p)^.vscrollbar, GTK_CAN_FOCUS); 179 gtk_scrolled_window_set_policy(PGtkScrolledWindow(p), 180 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 181 gtk_scrolled_window_set_shadow_type(PGtkScrolledWindow(p), GTK_SHADOW_IN); 182 gtk_widget_show(p); 183 184 liststore := gtk_list_store_new (4, 185 [G_TYPE_UCHAR, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, nil]); 186 TreeViewWidget := gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore)); 187 g_object_unref(G_OBJECT(liststore)); 188 189 // Check Column 190 renderer := gtk_cell_renderer_toggle_new(); 191 {$ifdef windows} 192 // standard indicator size = 13 and its looks ugly under windows 193 g_object_set(renderer, 'indicator-size', [14, nil]); 194 {$endif} 195 column := gtk_tree_view_column_new; 196 gtk_tree_view_column_set_title(column, 'CHECKBTNS'); 197 gtk_tree_view_column_pack_start(column, renderer, True); 198 gtk_tree_view_column_set_cell_data_func(column, renderer, 199 @Gtk2WS_CheckListBoxDataFunc, WidgetInfo, nil); 200 gtk_cell_renderer_toggle_set_active(GTK_CELL_RENDERER_TOGGLE(renderer), True); 201 gtk_tree_view_append_column(GTK_TREE_VIEW(TreeViewWidget), column); 202 gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column), True); 203 204 SignalConnect(PGtkWidget(renderer), 'toggled', @Gtk2WS_CheckListBoxToggle, WidgetInfo); 205 206 // Text Column 207 renderer := LCLIntfCellRenderer_New; // gtk_cell_renderer_text_new(); 208 column := gtk_tree_view_column_new_with_attributes( 209 'LISTITEMS', renderer, ['text', gtk2CLBText, nil]); 210 211 gtk_tree_view_column_set_cell_data_func(Column, renderer, TGtkTreeCellDataFunc(@LCLIntfCellRenderer_CellDataFunc), WidgetInfo, nil); 212 gtk_tree_view_append_column(GTK_TREE_VIEW(TreeViewWidget), column); 213 gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column), True); 214 215 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(TreeViewWidget), False); 216 217 gtk_container_add(GTK_CONTAINER(p), TreeViewWidget); 218 gtk_widget_show(TreeViewWidget); 219 220 SetMainWidget(p, TreeViewWidget); 221 GetOrCreateWidgetInfo(p)^.CoreWidget := TreeViewWidget; 222 223 Selection := gtk_tree_view_get_selection(PGtkTreeView(TreeViewWidget)); 224 225 case TCustomCheckListBox(AWinControl).MultiSelect of 226 True : gtk_tree_selection_set_mode(Selection, GTK_SELECTION_MULTIPLE); 227 False: gtk_tree_selection_set_mode(Selection, GTK_SELECTION_SINGLE); 228 end; 229 230 g_signal_connect_after(Selection, 'changed', 231 G_CALLBACK(@Gtk2WS_CheckListBoxSelectionChanged), WidgetInfo); 232 233 Set_RC_Name(AWinControl, P); 234 if not AWinControl.HandleObjectShouldBeVisible and not (csDesigning in AWinControl.ComponentState) then 235 gtk_widget_hide(p); 236 SetCallbacks(p, WidgetInfo); 237end; 238 239class function TGtk2WSCustomCheckListBox.GetItemEnabled( 240 const ACheckListBox: TCustomCheckListBox; const AIndex: integer): Boolean; 241var 242 Iter : TGtkTreeIter; 243 TreeView: PGtkTreeView; 244 WidgetInfo: PWidgetInfo; 245 ListStore: PGtkTreeModel; 246 Disabled: gboolean; 247begin 248 Result := True; 249 WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle)); 250 251 TreeView := PGtkTreeView(WidgetInfo^.CoreWidget); 252 ListStore := gtk_tree_view_get_model(TreeView); 253 if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then 254 begin 255 gtk_tree_model_get(ListStore, @Iter, [gtk2CLBDisabled, @Disabled, -1]); 256 Result := not Disabled; 257 end; 258end; 259 260class function TGtk2WSCustomCheckListBox.GetState( 261 const ACheckListBox: TCustomCheckListBox; const AIndex: integer 262 ): TCheckBoxState; 263var 264 Iter : TGtkTreeIter; 265 TreeView: PGtkTreeView; 266 WidgetInfo: PWidgetInfo; 267 ListStore: PGtkTreeModel; 268 b: byte; 269begin 270 Result := cbUnchecked; 271 WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle)); 272 273 TreeView := PGtkTreeView(WidgetInfo^.CoreWidget); 274 ListStore := gtk_tree_view_get_model(TreeView); 275 if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then 276 begin 277 gtk_tree_model_get(ListStore, @Iter, [gtk2CLBState, @b, -1]); 278 Result := TCheckBoxState(b); 279 end; 280end; 281 282class procedure TGtk2WSCustomCheckListBox.SetItemEnabled( 283 const ACheckListBox: TCustomCheckListBox; const AIndex: integer; 284 const AEnabled: Boolean); 285var 286 Iter : TGtkTreeIter; 287 TreeView: PGtkTreeView; 288 WidgetInfo: PWidgetInfo; 289 ListStore: PGtkTreeModel; 290 Disabled: gboolean; 291begin 292 WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle)); 293 294 TreeView := PGtkTreeView(WidgetInfo^.CoreWidget); 295 ListStore := gtk_tree_view_get_model(TreeView); 296 if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then begin 297 Disabled:=not AEnabled; 298 gtk_list_store_set(ListStore, @Iter, [gtk2CLBDisabled, Disabled, -1]); 299 end; 300end; 301 302class procedure TGtk2WSCustomCheckListBox.SetState( 303 const ACheckListBox: TCustomCheckListBox; const AIndex: integer; 304 const AState: TCheckBoxState); 305var 306 Iter : TGtkTreeIter; 307 TreeView: PGtkTreeView; 308 WidgetInfo: PWidgetInfo; 309 ListStore: PGtkTreeModel; 310begin 311 WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle)); 312 313 TreeView := PGtkTreeView(WidgetInfo^.CoreWidget); 314 ListStore := gtk_tree_view_get_model(TreeView); 315 if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then 316 begin 317 gtk_list_store_set(ListStore, @Iter, [gtk2CLBState, Byte(AState), -1]); 318 end; 319end; 320 321end. 322