mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-10 08:08:00 +02:00
gtk2 intf: rewrite of the combobox code from Andrew Haines
git-svn-id: trunk@10896 -
This commit is contained in:
parent
e6a93d83e7
commit
62b4e66473
@ -5,7 +5,7 @@
|
||||
<CompilerOptions>
|
||||
<Version Value="5"/>
|
||||
<SearchPaths>
|
||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)/$(LCLWidgetType)/"/>
|
||||
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)/$(LCLWidgetType)"/>
|
||||
</SearchPaths>
|
||||
<CodeGeneration>
|
||||
<Generate Value="Faster"/>
|
||||
|
@ -3773,10 +3773,13 @@ begin
|
||||
|
||||
LM_FOCUS :
|
||||
begin
|
||||
{$IFDEF GTK1}
|
||||
if (ALCLObject is TCustomComboBox) then begin
|
||||
ConnectFocusEvents(PgtkObject(PgtkCombo(gObject)^.entry));
|
||||
ConnectFocusEvents(PgtkObject(PgtkCombo(gObject)^.list));
|
||||
end else begin
|
||||
end else
|
||||
{$ENDIF}
|
||||
begin
|
||||
ConnectFocusEvents(gCore);
|
||||
end;
|
||||
end;
|
||||
@ -3794,10 +3797,13 @@ begin
|
||||
LM_SYSKEYUP:
|
||||
begin
|
||||
//debugln('TGtkWidgetSet.SetCallback A KEY ALCLObject=',DbgSName(ALCLObject),' AMsg=',dbgs(AMsg));
|
||||
{$IFDEF GTK1}
|
||||
if (ALCLObject is TCustomComboBox) then begin
|
||||
ConnectKeyPressReleaseEvents(PgtkObject(PgtkCombo(gObject)^.entry));
|
||||
end
|
||||
else if (ALCLObject is TCustomForm) then begin
|
||||
else
|
||||
{$ENDIF}
|
||||
if (ALCLObject is TCustomForm) then begin
|
||||
ConnectKeyPressReleaseEvents(gObject);
|
||||
end;
|
||||
ConnectKeyPressReleaseEvents(gCore);
|
||||
@ -3829,6 +3835,7 @@ begin
|
||||
|
||||
LM_MOUSEMOVE:
|
||||
begin
|
||||
{$IFDEF GTK1}
|
||||
if (ALCLObject is TCustomComboBox) then
|
||||
begin
|
||||
ConnectSenderSignal(PgtkObject(PgtkCombo(gObject)^.entry),
|
||||
@ -3845,7 +3852,9 @@ begin
|
||||
'motion-notify-event',
|
||||
@GTKMotionNotifyAfter, GDK_POINTER_MOTION_MASK);
|
||||
end
|
||||
else begin
|
||||
else
|
||||
{$ENDIF}
|
||||
begin
|
||||
ConnectSenderSignal(gFixed, 'motion-notify-event', @GTKMotionNotify,
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
ConnectSenderSignalAfter(gFixed, 'motion-notify-event',
|
||||
@ -3858,6 +3867,7 @@ begin
|
||||
LM_MBUTTONDOWN,
|
||||
LM_MOUSEWHEEL :
|
||||
begin
|
||||
{$IFDEF GTK1}
|
||||
if (ALCLObject is TCustomComboBox) then
|
||||
begin
|
||||
ConnectSenderSignal(PgtkObject(PgtkCombo(gObject)^.entry),
|
||||
@ -3874,7 +3884,9 @@ begin
|
||||
// ConnectSenderSignal(PgtkObject(PgtkCOmbo(gObject)^.list),
|
||||
// 'button-press-event', @gtkMouseBtnPress, GDK_BUTTON_PRESS_MASK);
|
||||
end
|
||||
else begin
|
||||
else
|
||||
{$ENDIF}
|
||||
begin
|
||||
ConnectSenderSignal(gFixed, 'button-press-event', @gtkMouseBtnPress,
|
||||
GDK_BUTTON_PRESS_MASK);
|
||||
ConnectSenderSignalAfter(gFixed, 'button-press-event',
|
||||
@ -3886,6 +3898,7 @@ begin
|
||||
LM_RBUTTONUP,
|
||||
LM_MBUTTONUP:
|
||||
begin
|
||||
{$IFDEF GTK1}
|
||||
if (ALCLObject is TCustomComboBox) then
|
||||
Begin
|
||||
ConnectSenderSignal(PgtkObject(PgtkCombo(gObject)^.entry),
|
||||
@ -3904,7 +3917,9 @@ begin
|
||||
// 'button-release-event', @gtkMouseBtnRelease,
|
||||
// GDK_BUTTON_RELEASE_MASK);
|
||||
end
|
||||
else begin
|
||||
else
|
||||
{$ENDIF}
|
||||
begin
|
||||
ConnectSenderSignal(gFixed, 'button-release-event', @gtkMouseBtnRelease,
|
||||
GDK_BUTTON_RELEASE_MASK);
|
||||
ConnectSenderSignalAfter(gFixed, 'button-release-event',
|
||||
|
@ -71,13 +71,15 @@ var
|
||||
Msg: TLMDrawListItem;
|
||||
ItemPath: PGtkTreePath;
|
||||
Column: PGtkTreeViewColumn;
|
||||
Menu: PGtkMenuShell;
|
||||
MenuItem: PGtkMenuItem;
|
||||
begin
|
||||
{DebugLn(['LCLIntfCellRenderer_Render cell=',dbgs(cell),
|
||||
' ',GetWidgetDebugReport(Widget),' ',
|
||||
' background_area=',dbgGRect(background_area),
|
||||
' cell_area=',dbgGRect(cell_area),
|
||||
' expose_area=',dbgGRect(expose_area)]);}
|
||||
|
||||
|
||||
// draw default
|
||||
CellClass:=PLCLIntfCellRendererClass(gtk_object_get_class(cell));
|
||||
CellClass^.DefaultGtkRender(cell,Window,Widget,background_area,cell_area,
|
||||
@ -100,7 +102,11 @@ begin
|
||||
exit;
|
||||
|
||||
// get itemindex and area
|
||||
ItemIndex:=0;
|
||||
|
||||
AreaRect:=Bounds(background_area^.x,background_area^.y,
|
||||
background_area^.Width,background_area^.Height);
|
||||
|
||||
ItemIndex:=-1;
|
||||
if GTK_IS_TREE_VIEW(Widget) then begin
|
||||
//check the four possible corners of the cell
|
||||
if gtk_tree_view_get_path_at_pos(PGtkTreeView(Widget),cell_area^.x, cell_area^.y, ItemPath, column, nil, nil)
|
||||
@ -109,10 +115,26 @@ begin
|
||||
or gtk_tree_view_get_path_at_pos(PGtkTreeView(Widget),cell_area^.x+cell_area^.width, cell_area^.y+cell_area^.height, ItemPath, column, nil, nil)
|
||||
then
|
||||
ItemIndex := StrToInt(gtk_tree_path_to_string(ItemPath));
|
||||
end;
|
||||
end
|
||||
else if AWinControl is TCustomComboBox then begin
|
||||
MenuItem := g_object_get_data(G_OBJECT(cell), 'MenuItem');
|
||||
if MenuItem <> nil then begin
|
||||
Menu := PGtkMenuShell(gtk_widget_get_parent(PGtkWidget(MenuItem)));
|
||||
if Menu <> nil then
|
||||
ItemIndex := g_list_index(Menu^.children, MenuItem);
|
||||
if ItemIndex > -1 then begin
|
||||
AreaRect:=Bounds(0,0,
|
||||
PGtkWidget(MenuItem)^.allocation.Width,PGtkWidget(MenuItem)^.allocation.height);
|
||||
end;
|
||||
end
|
||||
else begin // it is a renderer not in the dropdown but the combo renderer itself
|
||||
ItemIndex := TCustomComboBox(AWinControl).ItemIndex;
|
||||
AreaRect:=Bounds(0,0, Widget^.allocation.Width, Widget^.allocation.height);
|
||||
end;
|
||||
|
||||
AreaRect:=Bounds(background_area^.x,background_area^.y,
|
||||
background_area^.Width,background_area^.Height);
|
||||
end;
|
||||
|
||||
if ItemIndex < 0 then ItemIndex := 0;
|
||||
|
||||
// collect state flags
|
||||
State:=[odPainted];
|
||||
|
@ -44,4 +44,35 @@ begin
|
||||
Result:=TextOut(DC,X,Y,Str,Count);
|
||||
end;
|
||||
|
||||
function TGtk2WidgetSet.ComboBoxDropDown(Handle: HWND; DropDown: boolean): boolean;
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Combo: PGtkComboBox;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(Handle), False);
|
||||
Combo := PGtkComboBox(WidgetInfo^.CoreWidget);
|
||||
|
||||
case DropDown of
|
||||
True : gtk_combo_box_popup(Combo);
|
||||
False: gtk_combo_box_popdown(Combo);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TGtk2WidgetSet.SetComboMinDropDownSize(Handle: HWND; MinItemsWidth,
|
||||
MinItemsHeight, MinItemCount: integer): boolean;
|
||||
var
|
||||
p: PGtkWidget;
|
||||
Menu: PGtkWidget;
|
||||
Requisition: TGtkRequisition;
|
||||
begin
|
||||
Result:=True;
|
||||
p := GetWidgetInfo(Pointer(Handle), False)^.CoreWidget;
|
||||
|
||||
Menu := PGtkWidget(g_object_get_data(G_OBJECT(p), 'Menu'));
|
||||
|
||||
Requisition.width := MinItemsWidth;
|
||||
Requisition.height := MinItemsHeight * MinItemCount;
|
||||
gtk_widget_size_request(Menu, @Requisition);
|
||||
end;
|
||||
|
||||
//##apiwiz##eps## // Do not remove, no wizard declaration after this line
|
||||
|
@ -32,6 +32,8 @@
|
||||
function ExtUTF8Out(DC: HDC; X, Y: Integer; Options: Longint; Rect: PRect;
|
||||
Str: PChar; Count: Longint; Dx: PInteger): Boolean; override;
|
||||
function TextUTF8Out(DC: HDC; X, Y: Integer; Str: PChar; Count: Longint): Boolean; override;
|
||||
function ComboBoxDropDown(Handle: HWND; DropDown: boolean): boolean; override;
|
||||
function SetComboMinDropDownSize(Handle: HWND; MinItemsWidth, MinItemsHeight, MinItemCount: integer): boolean; override;
|
||||
|
||||
|
||||
//##apiwiz##eps## // Do not remove, no wizard declaration after this line
|
||||
|
@ -23,7 +23,7 @@
|
||||
unit Gtk2WSStdCtrls;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
{$PACKRECORDS c}
|
||||
interface
|
||||
|
||||
uses
|
||||
@ -42,6 +42,28 @@ uses
|
||||
|
||||
type
|
||||
|
||||
|
||||
PGtkComboBoxPrivate = ^TGtkComboBoxPrivate;
|
||||
TGtkComboBoxPrivate = record
|
||||
model: PGtkTreeModel;
|
||||
col_column,
|
||||
row_column: gint;
|
||||
wrap_width: gint;
|
||||
active_row: PGtkTreeRowReference;
|
||||
tree_view: PGtkWidget;
|
||||
column: PGtkTreeViewColumn;
|
||||
cell_view: PGtkWidget;
|
||||
cell_view_frame: PGtkWidget;
|
||||
button: PGtkwidget;
|
||||
box: PGtkWidget;
|
||||
arrow: PGtkWidget;
|
||||
serarator: PGtkWidget;
|
||||
popup_widget: PGtkWidget;
|
||||
popup_window: PGtkWidget;
|
||||
popup_frame: PGtkWidget;
|
||||
scrolled_window: PGtkwidget;
|
||||
end;
|
||||
|
||||
{ TGtk2WSScrollBar }
|
||||
|
||||
TGtk2WSScrollBar = class(TGtkWSScrollBar)
|
||||
@ -71,8 +93,32 @@ type
|
||||
TGtk2WSCustomComboBox = class(TGtkWSCustomComboBox)
|
||||
private
|
||||
protected
|
||||
class procedure ReCreateCombo(const ACustomComboBox: TCustomComboBox; const AWithEntry: Boolean; const AWidgetInfo: PWidgetInfo); virtual;
|
||||
class procedure SetRenderer(const ACustomComboBox: TCustomComboBox; AWidget: PGtkWidget); virtual;
|
||||
class procedure SetCallbacks(const AWinControl: tWinControl; const AWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); virtual;
|
||||
public
|
||||
class function GetSelStart(const ACustomComboBox: TCustomComboBox): integer; override;
|
||||
class function GetSelLength(const ACustomComboBox: TCustomComboBox): integer; override;
|
||||
class function GetItemIndex(const ACustomComboBox: TCustomComboBox): integer; override;
|
||||
class function GetMaxLength(const ACustomComboBox: TCustomComboBox): integer; override;
|
||||
class function GetText(const AWinControl: TWinControl; var AText: String): Boolean; override;
|
||||
|
||||
class procedure SetArrowKeysTraverseList(const ACustomComboBox: TCustomComboBox;
|
||||
NewTraverseList: boolean); override;
|
||||
class procedure SetSelStart(const ACustomComboBox: TCustomComboBox; NewStart: integer); override;
|
||||
class procedure SetSelLength(const ACustomComboBox: TCustomComboBox; NewLength: integer); override;
|
||||
class procedure SetItemIndex(const ACustomComboBox: TCustomComboBox; NewIndex: integer); override;
|
||||
class procedure SetMaxLength(const ACustomComboBox: TCustomComboBox; NewLength: integer); override;
|
||||
class procedure SetStyle(const ACustomComboBox: TCustomComboBox; NewStyle: TComboBoxStyle); override;
|
||||
class procedure SetReadOnly(const ACustomComboBox: TCustomComboBox; NewReadOnly: boolean); override;
|
||||
|
||||
class function GetItems(const ACustomComboBox: TCustomComboBox): TStrings; override;
|
||||
class procedure Sort(const ACustomComboBox: TCustomComboBox; AList: TStrings; IsSorted: boolean); override;
|
||||
class procedure SetColor(const AWinControl: TWinControl); override;
|
||||
class procedure SetFont(const AWinControl: TWinControl; const AFont : tFont); override;
|
||||
class procedure SetText(const AWinControl: TWinControl; const AText: String); override;
|
||||
|
||||
class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
|
||||
end;
|
||||
|
||||
{ TGtk2WSComboBox }
|
||||
@ -243,7 +289,7 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses GtkWSControls;
|
||||
uses GtkWSControls, LCLMessageGlue;
|
||||
|
||||
{$I gtk2memostrings.inc}
|
||||
|
||||
@ -627,7 +673,391 @@ begin
|
||||
Result := ABS(Entry^.current_pos - Entry^.selection_bound);
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.ReCreateCombo(
|
||||
const ACustomComboBox: TCustomComboBox; const AWithEntry: Boolean;
|
||||
const AWidgetInfo: PWidgetInfo);
|
||||
var
|
||||
p: PGtkWidget;
|
||||
Model: PGtkTreeModel;
|
||||
Index: Integer;
|
||||
Text: String;
|
||||
begin
|
||||
p := AWidgetInfo^.CoreWidget;
|
||||
Model := gtk_combo_box_get_model(PGtkComboBox(p));
|
||||
g_object_ref(G_OBJECT(Model));
|
||||
|
||||
// this should work but may not in all circumstances
|
||||
Index := -1;
|
||||
if AWithEntry = False then begin // the current widget HAS an entry
|
||||
GetText(ACustomComboBox, Text);
|
||||
Index := ACustomComboBox.Items.IndexOf(Text);
|
||||
end;
|
||||
if Index = -1 then Index := GetItemIndex(ACustomComboBox);
|
||||
|
||||
gtk_widget_destroy(p);
|
||||
|
||||
case AWithEntry of
|
||||
True : p := gtk_combo_box_entry_new_with_model(Model, 0);
|
||||
False: p := gtk_combo_box_new_with_model(Model);
|
||||
end;
|
||||
SetMainWidget(p, GTK_BIN(p)^.child);
|
||||
g_object_unref (G_OBJECT(Model));
|
||||
AWidgetInfo^.CoreWidget := p;
|
||||
gtk_object_set_data(Pointer(p), 'widgetinfo', AWidgetInfo);
|
||||
|
||||
SetItemIndex(ACustomComboBox, Index);
|
||||
|
||||
if AWithEntry then begin
|
||||
SetMaxLength(ACustomComboBox, TComboBox(ACustomComboBox).MaxLength);
|
||||
SetReadOnly(ACustomComboBox, ACustomComboBox.ReadOnly);
|
||||
end;
|
||||
|
||||
SetRenderer(ACustomComboBox, p);
|
||||
|
||||
gtk_container_add(PGtkContainer(AWidgetInfo^.ClientWidget), p);
|
||||
gtk_widget_show_all(AWidgetInfo^.ClientWidget);
|
||||
|
||||
SetCallbacks(ACustomComboBox, p, AWidgetInfo);
|
||||
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetRenderer(
|
||||
const ACustomComboBox: TCustomComboBox; AWidget: PGtkWidget);
|
||||
var
|
||||
renderer : PGtkCellRenderer;
|
||||
begin
|
||||
renderer := LCLIntfCellRenderer_New();
|
||||
gtk_cell_layout_clear(PGtkCellLayout(AWidget));
|
||||
gtk_cell_layout_pack_start(PGtkCellLayout(AWidget), renderer, True);
|
||||
gtk_cell_layout_set_attributes(PGtkCellLayout(AWidget), renderer, ['text', 0, nil]);
|
||||
end;
|
||||
|
||||
procedure UpdateMenuItemsCB(AMenuItem: PGtkBin; WidgetInfo: PWidgetInfo); cdecl;
|
||||
var
|
||||
renderer : PGtkCellRenderer;
|
||||
AItem: PGtkCellLayout;
|
||||
// AItem is really a GtkCellView which implements GtkCellRenderer
|
||||
begin
|
||||
AItem := PGtkCellLayout(AMenuItem^.child);
|
||||
//WriteLn(G_OBJECT_CLASS_NAME(GTK_WIDGET_GET_CLASS(PGtkWidget(AItem))));
|
||||
|
||||
if g_object_get_data(G_OBJECT(AItem), 'MenuItem') <> nil then exit;
|
||||
|
||||
renderer := LCLIntfCellRenderer_New();
|
||||
gtk_cell_layout_clear(AItem);
|
||||
gtk_cell_layout_pack_start(AItem, renderer, True);
|
||||
gtk_cell_layout_set_attributes(AItem, renderer, ['text', 0, nil]);
|
||||
SetMainWidget(WidgetInfo^.CoreWidget, AItem);
|
||||
g_object_set_data(G_OBJECT(AItem), 'MenuItem', AMenuItem);
|
||||
g_object_set_data(G_OBJECT(renderer), 'MenuItem', AMenuItem);
|
||||
end;
|
||||
|
||||
procedure GtkPopupShowCB(AMenu: PGtkMenuShell; WidgetInfo: PWidgetInfo); cdecl;
|
||||
begin
|
||||
// here we insure that the combo's menu items are using our internal renderer
|
||||
// so we can use custom drawing
|
||||
g_list_foreach(AMenu^.children, TGFunc(@UpdateMenuItemsCB), WidgetInfo);
|
||||
|
||||
LCLSendDropDownMsg(TControl(WidgetInfo^.LCLObject));
|
||||
end;
|
||||
|
||||
procedure GtkChangedCB(AWidget: PGtkWidget; WidgetInfo: PWidgetInfo); cdecl;
|
||||
begin
|
||||
LCLSendChangedMsg(TControl(WidgetInfo^.LCLObject));
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetCallbacks(
|
||||
const AWinControl: TWinControl; const AWidget: PGtkWidget;
|
||||
const AWidgetInfo: PWidgetInfo);
|
||||
var
|
||||
AGtkObject: PGtkObject;
|
||||
AChild: PGtkObject;
|
||||
AButton: PGtkObject;
|
||||
APrivate: PGtkComboBoxPrivate;
|
||||
AMenu: PGtkMenu;
|
||||
BtnPressID: guint;
|
||||
HandlerID: guint;
|
||||
begin
|
||||
AGtkObject := PGtkObject(AWidget);
|
||||
AChild := PGtkObject(PGtkBin(AWidget)^.child);
|
||||
APrivate := PGtkComboBoxPrivate(PGtkComboBox(AWidget)^.priv);
|
||||
AButton := PGtkObject(APrivate^.button);
|
||||
|
||||
// we have to remove the handler gtk sets up because we will never get the mouse down messages
|
||||
BtnPressID := g_signal_lookup('button_press_event', GTK_TYPE_COMBO_BOX);
|
||||
HandlerID := g_signal_handler_find(AButton, G_SIGNAL_MATCH_ID, BtnPressID, 0, nil, nil, nil);
|
||||
if HandlerID > 0 then begin
|
||||
g_signal_handler_disconnect(AButton, HandlerID);
|
||||
end;
|
||||
|
||||
g_signal_connect(AWidget, 'changed', TGCallback(@GtkChangedCB), AWidgetInfo);
|
||||
|
||||
// First the combo
|
||||
Gtk2WidgetSet.SetCallback(LM_MOUSEMOVE, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_LBUTTONDOWN, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_LBUTTONUP, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_LBUTTONDBLCLK, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_RBUTTONDBLCLK, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MBUTTONDBLCLK, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_RBUTTONDOWN, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_RBUTTONUP, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MBUTTONDOWN, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MBUTTONUP, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MOUSEWHEEL, AGTKObject, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_PAINT, AGTKObject, AWinControl);
|
||||
|
||||
//And now the same for the Button in the combo
|
||||
|
||||
Gtk2WidgetSet.SetCallback(LM_MOUSEENTER, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MOUSELEAVE, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MOUSEMOVE, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_LBUTTONDOWN, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_LBUTTONUP, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_LBUTTONUP, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_RBUTTONDOWN, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_RBUTTONUP, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MBUTTONDOWN, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MBUTTONUP, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_MOUSEWHEEL, AButton, AWinControl);
|
||||
Gtk2WidgetSet.SetCallback(LM_PAINT, AGTKObject, AWinControl);
|
||||
|
||||
// if we are a GtkComboBoxEntry
|
||||
if GtkWidgetIsA(PGtkWidget(AChild), GTK_TYPE_ENTRY) then begin
|
||||
// Anything?
|
||||
end;
|
||||
|
||||
g_signal_connect(APrivate^.popup_widget, 'show', TGCallback(@GtkPopupShowCB), AWidgetInfo);
|
||||
g_object_set_data(G_OBJECT(AWidget), 'Menu', APrivate^.popup_widget);
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.GetSelStart(
|
||||
const ACustomComboBox: TCustomComboBox): integer;
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkEntry;
|
||||
begin
|
||||
Result := 0;
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
// if the combo is an editable ...
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_ENTRY(GTK_BIN(WidgetInfo^.CoreWidget)^.child);
|
||||
Result := Min(Entry^.current_pos, Entry^.selection_bound);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.GetSelLength(
|
||||
const ACustomComboBox: TCustomComboBox): integer;
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkEntry;
|
||||
begin
|
||||
Result := 0;
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
// if the combo is an editable ...
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_ENTRY(GTK_BIN(WidgetInfo^.CoreWidget)^.child);
|
||||
Result := ABS(Entry^.current_pos - Entry^.selection_bound);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.GetItemIndex(
|
||||
const ACustomComboBox: TCustomComboBox): integer;
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkEntry;
|
||||
Text: String;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
Result := gtk_combo_box_get_active(PGtkComboBox(WidgetInfo^.CoreWidget));
|
||||
|
||||
// if the combo is an editable ...
|
||||
if (Result = -1) and gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_ENTRY(GTK_BIN(WidgetInfo^.CoreWidget)^.child);
|
||||
Text := gtk_entry_get_text(Entry);
|
||||
Result := ACustomComboBox.Items.IndexOf(Text);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.GetMaxLength(
|
||||
const ACustomComboBox: TCustomComboBox): integer;
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkEntry;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
// if the combo is an editable ...
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_ENTRY(GTK_BIN(WidgetInfo^.CoreWidget)^.child);
|
||||
Result := gtk_entry_get_max_length(Entry);
|
||||
end
|
||||
else begin
|
||||
Result := PtrInt(g_object_get_data(PGObject(WidgetInfo^.ClientWidget), 'max-length'));
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.GetText(const AWinControl: TWinControl;
|
||||
var AText: String): Boolean;
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkWidget;
|
||||
Index: Integer;
|
||||
begin
|
||||
Result := True;
|
||||
WidgetInfo := GetWidgetInfo(Pointer(AWinControl.Handle));
|
||||
|
||||
// if the combo is an editable ...
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
AText := gtk_entry_get_text(PGtkEntry(Entry));
|
||||
exit;
|
||||
end;
|
||||
|
||||
// if we are a fixed un-editable combo then ...
|
||||
Index := GetItemIndex(TCustomComboBox(AWinControl));
|
||||
if Index > -1 then AText := TCustomComboBox(AWinControl).Items.Strings[Index]
|
||||
else Result := False;
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetArrowKeysTraverseList(
|
||||
const ACustomComboBox: TCustomComboBox; NewTraverseList: boolean);
|
||||
begin
|
||||
// TODO
|
||||
// This is not an option that is available for this widget
|
||||
// we will have to eat the keystrokes to set this to false
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetSelStart(
|
||||
const ACustomComboBox: TCustomComboBox; NewStart: integer);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkWidget;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
gtk_entry_select_region(PGtkEntry(Entry), NewStart, NewStart);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetSelLength(
|
||||
const ACustomComboBox: TCustomComboBox; NewLength: integer);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkWidget;
|
||||
Start: Integer;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
Start := GetSelStart(ACustomComboBox);
|
||||
gtk_entry_select_region(PGtkEntry(Entry), Start, NewLength);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetItemIndex(
|
||||
const ACustomComboBox: TCustomComboBox; NewIndex: integer);
|
||||
var
|
||||
P: PGtkWidget;
|
||||
begin
|
||||
p := GetWidgetInfo(Pointer(ACustomComboBox.Handle))^.CoreWidget;
|
||||
gtk_combo_box_set_active(PGtkComboBox(p), NewIndex)
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetMaxLength(
|
||||
const ACustomComboBox: TCustomComboBox; NewLength: integer);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkWidget;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
gtk_entry_set_max_length(PGtkEntry(Entry), NewLength);
|
||||
end;
|
||||
// We save this in the ClientWidget for when the Entry Changes styles
|
||||
g_object_set_data(PGObject(WidgetInfo^.ClientWidget), 'max-length', Pointer(PtrInt(NewLength)));
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetStyle(
|
||||
const ACustomComboBox: TCustomComboBox; NewStyle: TComboBoxStyle);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
p: PGtkWidget;
|
||||
begin
|
||||
if csDesigning in ACustomComboBox.ComponentState then exit;
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
p := WidgetInfo^.CoreWidget;
|
||||
case NewStyle of
|
||||
csDropDown,
|
||||
csSimple:
|
||||
begin
|
||||
if gtk_is_combo_box_entry(p) then Exit;
|
||||
ReCreateCombo(ACustomComboBox, True, WidgetInfo);
|
||||
end;
|
||||
csDropDownList,
|
||||
csOwnerDrawFixed,
|
||||
csOwnerDrawVariable:
|
||||
begin
|
||||
if not gtk_is_combo_box_entry(p) then Exit;
|
||||
ReCreateCombo(ACustomComboBox, False, WidgetInfo);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetReadOnly(
|
||||
const ACustomComboBox: TCustomComboBox; NewReadOnly: boolean);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkWidget;
|
||||
Start: Integer;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(ACustomComboBox.Handle));
|
||||
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
gtk_entry_set_editable(PGtkEntry(Entry), not NewReadOnly);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.GetItems(const ACustomComboBox: TCustomComboBox
|
||||
): TStrings;
|
||||
var
|
||||
Widget: PGtkWidget;// pointer to gtk-widget
|
||||
Handle: HWND;
|
||||
begin
|
||||
Handle := ACustomComboBox.Handle;
|
||||
|
||||
Widget := GetWidgetInfo(Pointer(Handle), True)^.CoreWidget;
|
||||
Result := TGtkListStoreStringList.Create(
|
||||
gtk_combo_box_get_model(PGtkComboBox(Widget)),
|
||||
0,
|
||||
ACustomComboBox);
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.Sort(const ACustomComboBox: TCustomComboBox;
|
||||
AList: TStrings; IsSorted: boolean);
|
||||
begin
|
||||
// TODO
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetColor(const AWinControl: TWinControl);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Child: PGtkWidget; // can be GtkCellRenderer or GtkEntry
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(AWinControl.Handle));
|
||||
|
||||
Child := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
Gtk2WidgetSet.SetWidgetColor(Child, AWinControl.Font.Color, AWinControl.Color,[GTK_STATE_NORMAL,GTK_STATE_ACTIVE,GTK_STATE_PRELIGHT,GTK_STATE_SELECTED,GTK_STYLE_BASE]);
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetFont(const AWinControl: TWinControl;
|
||||
const AFont : TFont);
|
||||
@ -648,6 +1078,67 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TGtk2WSCustomComboBox.SetText(const AWinControl: TWinControl;
|
||||
const AText: String);
|
||||
var
|
||||
WidgetInfo: PWidgetInfo;
|
||||
Entry: PGtkWidget;
|
||||
Index: Integer;
|
||||
begin
|
||||
WidgetInfo := GetWidgetInfo(Pointer(AWinControl.Handle));
|
||||
|
||||
if gtk_is_combo_box_entry(WidgetInfo^.CoreWidget) then begin
|
||||
Entry := GTK_BIN(WidgetInfo^.CoreWidget)^.child;
|
||||
gtk_entry_set_text(PGtkEntry(Entry), PChar(AText));
|
||||
end;
|
||||
|
||||
// if not an entry it is a readonly list so we will try to comply by matching the text to an item
|
||||
Index := TCustomComboBox(AWinControl).Items.IndexOf(AText);
|
||||
SetItemIndex(TCustomComboBox(AWinControl), Index);
|
||||
end;
|
||||
|
||||
class function TGtk2WSCustomComboBox.CreateHandle(const AWinControl: TWinControl;
|
||||
const AParams: TCreateParams): TLCLIntfHandle;
|
||||
var
|
||||
Box, // this makes it easy to switch between GtkComBox and GtkComboBoxEntry
|
||||
p: PGtkWidget; // ptr to the newly created GtkWidget
|
||||
|
||||
ListStore : PGtkListStore;
|
||||
WidgetInfo: PWidgetInfo;
|
||||
begin
|
||||
Box := gtk_event_box_new;
|
||||
|
||||
WidgetInfo := CreateWidgetInfo(Box, AWinControl, AParams);
|
||||
|
||||
ListStore := gtk_list_store_new (2, [G_TYPE_STRING, G_TYPE_POINTER, nil]);
|
||||
|
||||
case TCustomComboBox(AWinControl).Style of
|
||||
csDropDown, csSimple: p := gtk_combo_box_entry_new_with_model(GTK_TREE_MODEL (ListStore), 0);
|
||||
csDropDownList,
|
||||
csOwnerDrawFixed,
|
||||
csOwnerDrawVariable : p := gtk_combo_box_new_with_model(GTK_TREE_MODEL (ListStore));
|
||||
end;
|
||||
|
||||
SetMainWidget(p, GTK_BIN(p)^.child);
|
||||
|
||||
g_object_unref (G_OBJECT (liststore));
|
||||
|
||||
gtk_container_add(PGtkContainer(Box), p);
|
||||
gtk_widget_show_all(Box);
|
||||
|
||||
SetRenderer(TCustomComboBox(AWinControl), p);
|
||||
|
||||
SetMainWidget(Box, p);
|
||||
WidgetInfo^.CoreWidget := p;
|
||||
WidgetInfo^.ClientWidget := Box;
|
||||
|
||||
//gtk_widget_add_events(Box, GDK_ALL_EVENTS_MASK);
|
||||
|
||||
SetCallbacks(AWinControl, p, WidgetInfo);
|
||||
|
||||
Result := TLCLIntfHandle(Box);
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
@ -83,6 +83,7 @@ function LCLSendDayChangedMsg(const Target: TControl): PtrInt;
|
||||
function LCLSendMouseMultiClickMsg(const Target: TControl; XPos, YPos: SmallInt; Button: TMouseButton; ClickCount: Byte = 2; ShiftState: TShiftState = []): PtrInt;
|
||||
function LCLSendDrawListItemMsg(const Target: TControl; const DrawListItemStruct: PDrawListItemStruct): PtrInt;
|
||||
function LCLSendInternalPaintMsg(const Target: TControl; DC: HDC): PtrInt;
|
||||
function LCLSendDropDownMsg(const Target: TControl): PtrInt;
|
||||
|
||||
implementation
|
||||
|
||||
@ -1184,6 +1185,30 @@ begin
|
||||
Result := DeliverMessage(Target, Mess);
|
||||
end;
|
||||
|
||||
{******************************************************************************
|
||||
* *
|
||||
* LCLSendDropDownMsg *
|
||||
* *
|
||||
* Returns : 0 to accept the message, non-zero to reject the message *
|
||||
* *
|
||||
* Params *
|
||||
* *
|
||||
* Target : The Control that will recieve the message CN_Command *
|
||||
* *
|
||||
* Used to notify a combo that the combobox is popping down *
|
||||
* *
|
||||
******************************************************************************}
|
||||
function LCLSendDropDownMsg(const Target: TControl): PtrInt;
|
||||
var
|
||||
Mess : TLMCommand;
|
||||
begin
|
||||
FillChar(Mess, SizeOf(Mess), 0);
|
||||
Mess.Msg := CN_Command;
|
||||
Mess.NotifyCode := CBN_DROPDOWN;
|
||||
|
||||
Result := DeliverMessage(Target, Mess);
|
||||
end;
|
||||
|
||||
|
||||
// Remove these lines as you implement the function
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user