lazarus/lcl/interfaces/gtk2/gtk2wschecklst.pp
2023-08-25 12:34:07 +02:00

320 lines
11 KiB
ObjectPascal

{ $Id$}
{
*****************************************************************************
* Gtk2WSCheckLst.pp *
* ----------------- *
* *
* *
*****************************************************************************
*****************************************************************************
This file is part of the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
}
unit Gtk2WSCheckLst;
{$mode objfpc}{$H+}
interface
uses
// RTL
SysUtils, Classes,
Gtk2, GLib2, Gtk2Def,
// LCL
////////////////////////////////////////////////////
// I M P O R T A N T
////////////////////////////////////////////////////
// To get as little as posible circles,
// uncomment only when needed for registration
////////////////////////////////////////////////////
CheckLst, StdCtrls, Controls, LCLType, LMessages, LCLProc,
////////////////////////////////////////////////////
WSCheckLst, WSLCLClasses,
Gtk2WSControls, Gtk2Proc, Gtk2CellRenderer;
type
{ TGtk2WSCheckListBox }
{ TGtk2WSCustomCheckListBox }
TGtk2WSCustomCheckListBox = class(TWSCustomCheckListBox)
private
class procedure SetCallbacks(const AGtkWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual;
published
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
class function GetItemEnabled(const ACheckListBox: TCustomCheckListBox;
const AIndex: integer): Boolean; override;
class function GetState(const ACheckListBox: TCustomCheckListBox;
const AIndex: integer): TCheckBoxState; override;
class procedure SetItemEnabled(const ACheckListBox: TCustomCheckListBox;
const AIndex: integer; const AEnabled: Boolean); override;
class procedure SetState(const ACheckListBox: TCustomCheckListBox;
const AIndex: integer; const AState: TCheckBoxState); override;
end;
implementation
const
gtk2CLBState = 0; // byte
gtk2CLBText = 1; // PGChar
gtk2CLBDisabled = 3; // gboolean
{ TGtk2WSCheckListBox }
function Gtk2WS_CheckListBoxSelectionChanged({%H-}Widget: PGtkWidget;
WidgetInfo: PWidgetInfo): gboolean; cdecl;
var
Mess: TLMessage;
begin
Result := False;
if WidgetInfo^.ChangeLock > 0 then
Exit;
FillChar(Mess{%H-},SizeOf(Mess),0);
Mess.msg := LM_SELCHANGE;
DeliverMessage(WidgetInfo^.LCLObject, Mess);
end;
procedure Gtk2WS_CheckListBoxDataFunc({%H-}tree_column: PGtkTreeViewColumn;
cell: PGtkCellRenderer; tree_model: PGtkTreeModel; iter: PGtkTreeIter; {%H-}data: Pointer); cdecl;
var
b: byte;
ADisabled: gboolean;
AValue: TCheckBoxState;
begin
gtk_tree_model_get(tree_model, iter, [gtk2CLBState, @b, -1]);
gtk_tree_model_get(tree_model, iter, [gtk2CLBDisabled, @ADisabled, -1]);
AValue := TCheckBoxState(b); // TCheckBoxState is 4 byte
g_object_set(cell, 'inconsistent', [gboolean(AValue = cbGrayed), nil]);
if AValue <> cbGrayed then
gtk_cell_renderer_toggle_set_active(PGtkCellRendererToggle(cell), AValue = cbChecked);
g_object_set(cell, 'activatable', [gboolean(not ADisabled), nil]);
end;
procedure Gtk2WS_CheckListBoxToggle({%H-}cellrenderertoggle : PGtkCellRendererToggle;
arg1 : PGChar; WidgetInfo: PWidgetInfo); cdecl;
var
Mess: TLMessage;
Param: PtrInt;
Iter : TGtkTreeIter;
TreeView: PGtkTreeView;
ListStore: PGtkTreeModel;
Path: PGtkTreePath;
AState: TCheckBoxState;
begin
{$IFDEF EventTrace}
EventTrace('Gtk2WS_CheckListBoxToggle', WidgetInfo^.LCLObject);
{$ENDIF}
Val(arg1, Param);
TreeView := PGtkTreeView(WidgetInfo^.CoreWidget);
ListStore := gtk_tree_view_get_model(TreeView);
if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, Param) then
begin
TCustomCheckListBox(WidgetInfo^.LCLObject).Toggle(Param);
AState:=TCustomCheckListBox(WidgetInfo^.LCLObject).State[Param];
gtk_list_store_set(ListStore, @Iter, [gtk2CLBState,
Byte(AState), -1]);
end;
Path := gtk_tree_path_new_from_indices(Param, -1);
if Path <> nil then
begin
if TreeView^.priv^.tree <> nil then
gtk_tree_view_set_cursor(TreeView, Path, nil, False);
gtk_tree_path_free(Path);
end;
FillChar(Mess{%H-}, SizeOf(Mess), #0);
Mess.Msg := LM_CHANGED;
Mess.Result := 0;
Mess.WParam := Param;
DeliverMessage(widgetInfo^.lclObject, Mess);
end;
class procedure TGtk2WSCustomCheckListBox.SetCallbacks(const AGtkWidget: PGtkWidget;
const AWidgetInfo: PWidgetInfo);
//var
// Selection: PGtkTreeSelection;
begin
TGtk2WSBaseScrollingWinControl.SetCallbacks(AGtkWidget,AWidgetInfo);
{Selection :=} gtk_tree_view_get_selection(PGtkTreeView(AWidgetInfo^.CoreWidget));
//SignalConnect(PGtkWidget(Selection), 'changed', @Gtk2WS_ListBoxChange, AWidgetInfo);
end;
class function TGtk2WSCustomCheckListBox.CreateHandle(
const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle;
var
TreeViewWidget: PGtkWidget;
p: PGtkWidget; // ptr to the newly created GtkWidget
liststore : PGtkListStore;
Selection: PGtkTreeSelection;
renderer : PGtkCellRenderer;
column : PGtkTreeViewColumn;
WidgetInfo: PWidgetInfo;
begin
Result := TGtk2WSBaseScrollingWinControl.CreateHandle(AWinControl,AParams);
p := {%H-}PGtkWidget(Result);
if Result = 0 then exit;
WidgetInfo := GetWidgetInfo(p);
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);
gtk_widget_show(p);
liststore := gtk_list_store_new (4,
[G_TYPE_UCHAR, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN, nil]);
TreeViewWidget := gtk_tree_view_new_with_model(GTK_TREE_MODEL(liststore));
g_object_unref(G_OBJECT(liststore));
// Check Column
renderer := gtk_cell_renderer_toggle_new();
{$ifdef windows}
// standard indicator size = 13 and its looks ugly under windows
g_object_set(renderer, 'indicator-size', [14, nil]);
{$endif}
column := gtk_tree_view_column_new;
gtk_tree_view_column_set_title(column, 'CHECKBTNS');
gtk_tree_view_column_pack_start(column, renderer, True);
gtk_tree_view_column_set_cell_data_func(column, renderer,
@Gtk2WS_CheckListBoxDataFunc, WidgetInfo, nil);
gtk_cell_renderer_toggle_set_active(GTK_CELL_RENDERER_TOGGLE(renderer), True);
gtk_tree_view_append_column(GTK_TREE_VIEW(TreeViewWidget), column);
gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column), True);
SignalConnect(PGtkWidget(renderer), 'toggled', @Gtk2WS_CheckListBoxToggle, WidgetInfo);
// Text Column
renderer := LCLIntfCellRenderer_New; // gtk_cell_renderer_text_new();
column := gtk_tree_view_column_new_with_attributes(
'LISTITEMS', renderer, ['text', gtk2CLBText, nil]);
gtk_tree_view_column_set_cell_data_func(Column, renderer, TGtkTreeCellDataFunc(@LCLIntfCellRenderer_CellDataFunc), WidgetInfo, nil);
gtk_tree_view_append_column(GTK_TREE_VIEW(TreeViewWidget), column);
gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(column), True);
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(TreeViewWidget), False);
gtk_container_add(GTK_CONTAINER(p), TreeViewWidget);
gtk_widget_show(TreeViewWidget);
SetMainWidget(p, TreeViewWidget);
GetOrCreateWidgetInfo(p)^.CoreWidget := TreeViewWidget;
Selection := gtk_tree_view_get_selection(PGtkTreeView(TreeViewWidget));
case TCustomCheckListBox(AWinControl).MultiSelect of
True : gtk_tree_selection_set_mode(Selection, GTK_SELECTION_MULTIPLE);
False: gtk_tree_selection_set_mode(Selection, GTK_SELECTION_SINGLE);
end;
g_signal_connect_after(Selection, 'changed',
G_CALLBACK(@Gtk2WS_CheckListBoxSelectionChanged), WidgetInfo);
Set_RC_Name(AWinControl, P);
if not AWinControl.HandleObjectShouldBeVisible and not (csDesigning in AWinControl.ComponentState) then
gtk_widget_hide(p);
SetCallbacks(p, WidgetInfo);
end;
class function TGtk2WSCustomCheckListBox.GetItemEnabled(
const ACheckListBox: TCustomCheckListBox; const AIndex: integer): Boolean;
var
Iter : TGtkTreeIter;
TreeView: PGtkTreeView;
WidgetInfo: PWidgetInfo;
ListStore: PGtkTreeModel;
Disabled: gboolean;
begin
Result := True;
WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle));
TreeView := PGtkTreeView(WidgetInfo^.CoreWidget);
ListStore := gtk_tree_view_get_model(TreeView);
if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then
begin
gtk_tree_model_get(ListStore, @Iter, [gtk2CLBDisabled, @Disabled, -1]);
Result := not Disabled;
end;
end;
class function TGtk2WSCustomCheckListBox.GetState(
const ACheckListBox: TCustomCheckListBox; const AIndex: integer
): TCheckBoxState;
var
Iter : TGtkTreeIter;
TreeView: PGtkTreeView;
WidgetInfo: PWidgetInfo;
ListStore: PGtkTreeModel;
b: byte;
begin
Result := cbUnchecked;
WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle));
TreeView := PGtkTreeView(WidgetInfo^.CoreWidget);
ListStore := gtk_tree_view_get_model(TreeView);
if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then
begin
gtk_tree_model_get(ListStore, @Iter, [gtk2CLBState, @b, -1]);
Result := TCheckBoxState(b);
end;
end;
class procedure TGtk2WSCustomCheckListBox.SetItemEnabled(
const ACheckListBox: TCustomCheckListBox; const AIndex: integer;
const AEnabled: Boolean);
var
Iter : TGtkTreeIter;
TreeView: PGtkTreeView;
WidgetInfo: PWidgetInfo;
ListStore: PGtkTreeModel;
Disabled: gboolean;
begin
WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle));
TreeView := PGtkTreeView(WidgetInfo^.CoreWidget);
ListStore := gtk_tree_view_get_model(TreeView);
if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then begin
Disabled:=not AEnabled;
gtk_list_store_set(ListStore, @Iter, [gtk2CLBDisabled, Disabled, -1]);
end;
end;
class procedure TGtk2WSCustomCheckListBox.SetState(
const ACheckListBox: TCustomCheckListBox; const AIndex: integer;
const AState: TCheckBoxState);
var
Iter : TGtkTreeIter;
TreeView: PGtkTreeView;
WidgetInfo: PWidgetInfo;
ListStore: PGtkTreeModel;
begin
WidgetInfo := GetWidgetInfo({%H-}PGtkWidget(ACheckListBox.Handle));
TreeView := PGtkTreeView(WidgetInfo^.CoreWidget);
ListStore := gtk_tree_view_get_model(TreeView);
if gtk_tree_model_iter_nth_child(ListStore, @Iter, nil, AIndex) then
begin
gtk_list_store_set(ListStore, @Iter, [gtk2CLBState, Byte(AState), -1]);
end;
end;
end.