mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-30 16:03:40 +02:00
320 lines
11 KiB
ObjectPascal
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.
|