lazarus/lcl/interfaces/qt/qtwsextctrls.pp
paul e720286a68 - all event attaching code moved to TQtWidget.AttachEvents, TQtWidget.DetachEvents and descendants
- initial implementation of Qt Caret by *Andreas Hausladen* with changes. Compile with -dShowQtCaret to test
- fixed bug caused memory corruption
- other minor fixes

git-svn-id: trunk@11465 -
2007-07-12 05:47:15 +00:00

643 lines
19 KiB
ObjectPascal
Raw Blame History

{ $Id$}
{
*****************************************************************************
* QtWSExtCtrls.pp *
* --------------- *
* *
* *
*****************************************************************************
*****************************************************************************
* *
* This file is part of the Lazarus Component Library (LCL) *
* *
* See the file COPYING.modifiedLGPL, 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. *
* *
*****************************************************************************
}
unit QtWSExtCtrls;
{$mode delphi}{$H+}
interface
uses
// Bindings
{$ifdef USE_QT_4_3}
qt43,
{$else}
qt4,
{$endif}
qtwidgets, qtobjects,
// LCL
SysUtils, Classes, Controls, Graphics, Forms, StdCtrls, ExtCtrls, LCLType,
// Widgetset
WSExtCtrls, WSLCLClasses;
type
{ TQtWSCustomPage }
TQtWSCustomPage = class(TWSCustomPage)
private
protected
public
class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): HWND; override;
class procedure DestroyHandle(const AWinControl: TWinControl); override;
// class procedure UpdateProperties(const ACustomPage: TCustomPage); override;
class procedure SetText(const AWinControl: TWinControl; const AText: string); override;
end;
{ TQtWSCustomNotebook }
TQtWSCustomNotebook = class(TWSCustomNotebook)
private
protected
public
class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): HWND; override;
class procedure DestroyHandle(const AWinControl: TWinControl); override;
class procedure AddAllNBPages(const ANotebook: TCustomNotebook);
{ class procedure AdjustSizeNotebookPages(const ANotebook: TCustomNotebook);}
class procedure AddPage(const ANotebook: TCustomNotebook;
const AChild: TCustomPage; const AIndex: integer); override;
{ class procedure MovePage(const ANotebook: TCustomNotebook;
const AChild: TCustomPage; const NewIndex: integer); override;
class procedure RemoveAllNBPages(const ANotebook: TCustomNotebook);
class procedure RemovePage(const ANotebook: TCustomNotebook;
const AIndex: integer); override;
class function GetPageRealIndex(const ANotebook: TCustomNotebook; AIndex: Integer): Integer; override;
class function GetTabIndexAtPos(const ANotebook: TCustomNotebook; const AClientPos: TPoint): integer; override;
class procedure SetPageIndex(const ANotebook: TCustomNotebook; const AIndex: integer); override;}
class procedure SetTabPosition(const ANotebook: TCustomNotebook; const ATabPosition: TTabPosition); override;
{class procedure ShowTabs(const ANotebook: TCustomNotebook; AShowTabs: boolean); override;}
end;
{ TQtWSPage }
TQtWSPage = class(TWSPage)
private
protected
public
end;
{ TQtWSNotebook }
TQtWSNotebook = class(TWSNotebook)
private
protected
public
end;
{ TQtWSShape }
TQtWSShape = class(TWSShape)
private
protected
public
end;
{ TQtWSCustomSplitter }
TQtWSCustomSplitter = class(TWSCustomSplitter)
private
protected
public
end;
{ TQtWSSplitter }
TQtWSSplitter = class(TWSSplitter)
private
protected
public
end;
{ TQtWSPaintBox }
TQtWSPaintBox = class(TWSPaintBox)
private
protected
public
end;
{ TQtWSCustomImage }
TQtWSCustomImage = class(TWSCustomImage)
private
protected
public
end;
{ TQtWSImage }
TQtWSImage = class(TWSImage)
private
protected
public
end;
{ TQtWSBevel }
TQtWSBevel = class(TWSBevel)
private
protected
public
end;
{ TQtWSCustomRadioGroup }
TQtWSCustomRadioGroup = class(TWSCustomRadioGroup)
private
protected
public
class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle; override;
class procedure DestroyHandle(const AWinControl: TWinControl); override;
class procedure ShowHide(const AWinControl: TWinControl); override;
end;
{ TQtWSRadioGroup }
TQtWSRadioGroup = class(TWSRadioGroup)
private
protected
public
end;
{ TQtWSCustomCheckGroup }
TQtWSCustomCheckGroup = class(TWSCustomCheckGroup)
private
protected
public
class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle; override;
class procedure DestroyHandle(const AWinControl: TWinControl); override;
class procedure ShowHide(const AWinControl: TWinControl); override;
end;
{ TQtWSCheckGroup }
TQtWSCheckGroup = class(TWSCheckGroup)
private
protected
public
end;
{ TQtWSCustomLabeledEdit }
TQtWSCustomLabeledEdit = class(TWSCustomLabeledEdit)
private
protected
public
end;
{ TQtWSLabeledEdit }
TQtWSLabeledEdit = class(TWSLabeledEdit)
private
protected
public
end;
{ TQtWSCustomPanel }
TQtWSCustomPanel = class(TWSCustomPanel)
private
protected
public
class function CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): HWND; override;
class procedure DestroyHandle(const AWinControl: TWinControl); override;
end;
{ TQtWSPanel }
TQtWSPanel = class(TWSPanel)
private
protected
public
end;
implementation
const
QTabWidgetTabPositionMap: array[TTabPosition] of QTabWidgetTabPosition =
(
{ tpTop } QTabWidgetNorth,
{ tpBottom } QTabWidgetSouth,
{ tpLeft } QTabWidgetWest,
{ tpRight } QTabWidgetEast
);
{ TQtWSCustomPanel }
{------------------------------------------------------------------------------
Method: TQtWSCustomPanel.CreateHandle
Params: None
Returns: Nothing
Allocates memory and resources for the control and shows it
------------------------------------------------------------------------------}
class function TQtWSCustomPanel.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): HWND;
var
QtFrame: TQtFrame;
begin
QtFrame := TQtFrame.Create(AWinControl, AParams);
QtFrame.AttachEvents;
// Set<65>s initial properties
QtFrame.setFrameShape(QFrameWinPanel);
QtFrame.setFrameShadow(QFrameRaised);
// Return the Handle
Result := THandle(QtFrame);
end;
{------------------------------------------------------------------------------
Method: TQtWSCustomGroupBox.DestroyHandle
Params: None
Returns: Nothing
Releases allocated memory and resources
------------------------------------------------------------------------------}
class procedure TQtWSCustomPanel.DestroyHandle(const AWinControl: TWinControl);
begin
TQtFrame(AWinControl.Handle).Free;
AWinControl.Handle := 0;
end;
{ TQtWSCustomPage }
{------------------------------------------------------------------------------
Method: TQtWSCustomPage.CreateHandle
Params: None
Returns: Nothing
Allocates memory and resources for the control and shows it
------------------------------------------------------------------------------}
class function TQtWSCustomPage.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): HWND;
var
QtWidget: TQtWidget;
begin
{$ifdef VerboseQt}
WriteLn('Trace:> [TQtWSCustomPage.CreateHandle]');
{$endif}
QtWidget := TQtWidget.CreatePage(AWinControl, AParams);
QtWidget.AttachEvents;
// Returns the Handle
Result := THandle(QtWidget);
{$ifdef VerboseQt}
WriteLn('Trace:< [TQtWSCustomPage.CreateHandle] Result: ', IntToStr(Result));
{$endif}
end;
{------------------------------------------------------------------------------
Method: TQtWSCustomPage.DestroyHandle
Params: None
Returns: Nothing
Releases allocated memory and resources
------------------------------------------------------------------------------}
class procedure TQtWSCustomPage.DestroyHandle(const AWinControl: TWinControl);
begin
TQtWidget(AWinControl.Handle).Free;
AWinControl.Handle := 0;
end;
class procedure TQtWSCustomPage.SetText(const AWinControl: TWinControl; const AText: string);
var
ANoteBook: TCustomNoteBook;
Index: Integer;
AWsText: WideString;
begin
if (AWinControl is TCustomPage) and
(AWinControl.Parent <> nil) and
(AWinControl.Parent is TCustomNotebook) then
begin
ANoteBook := TCustomNotebook(AWinControl.Parent);
Index := ANoteBook.IndexOf(TCustomPage(AWinControl));
AWsText := UTF8Decode(AText);
TQtTabWidget(ANoteBook.Handle).setTabText(Index, @AWsText);
end;
end;
{ TQtWSCustomNotebook }
{------------------------------------------------------------------------------
Method: TQtWSCustomNotebook.CreateHandle
Params: None
Returns: Nothing
Allocates memory and resources for the control and shows it
------------------------------------------------------------------------------}
class function TQtWSCustomNotebook.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): HWND;
var
QtTabWidget: TQtTabWidget;
begin
{$ifdef VerboseQt}
WriteLn('TQtWSCustomNotebook.CreateHandle');
{$endif}
QtTabWidget := TQtTabWidget.Create(AWinControl, AParams);
QtTabWidget.SetTabPosition(QTabWidgetTabPositionMap[TCustomNoteBook(AWinControl).TabPosition]);
QtTabWidget.AttachEvents;
// Returns the Handle
Result := THandle(QtTabWidget);
end;
{------------------------------------------------------------------------------
Method: TQtWSCustomNotebook.DestroyHandle
Params: None
Returns: Nothing
Releases allocated memory and resources
------------------------------------------------------------------------------}
class procedure TQtWSCustomNotebook.DestroyHandle(const AWinControl: TWinControl);
begin
TQtTabWidget(AWinControl.Handle).Free;
AWinControl.Handle := 0;
end;
class procedure TQtWSCustomNotebook.AddAllNBPages(const ANotebook: TCustomNotebook);
begin
end;
class procedure TQtWSCustomNotebook.AddPage(const ANotebook: TCustomNotebook;
const AChild: TCustomPage; const AIndex: integer);
var
Str: WideString;
begin
{$ifdef VerboseQt}
WriteLn('TQtWSCustomNotebook.AddPage');
{$endif}
Str := UTF8Decode(AChild.Caption);
TQtTabWidget(ANotebook.Handle).insertTab(AIndex, TQtWidget(AChild.Handle).Widget, @Str);
end;
class procedure TQtWSCustomNotebook.SetTabPosition(
const ANotebook: TCustomNotebook; const ATabPosition: TTabPosition);
begin
TQtTabWidget(ANotebook.Handle).SetTabPosition(QTabWidgetTabPositionMap[ATabPosition]);
end;
{ TQtWSCustomRadioGroup }
{------------------------------------------------------------------------------
Method: TQtWSCustomRadioGroup.CreateHandle
Params: None
Returns: Nothing
Allocates memory and resources for the control and shows it
------------------------------------------------------------------------------}
class function TQtWSCustomRadioGroup.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle;
var
QtGroupBox: TQtGroupBox;
Str: WideString;
i: Integer;
begin
QtGroupBox := TQtGroupBox.Create(AWinControl, AParams);
Str := UTF8Decode(AWinControl.Caption);
QGroupBox_setTitle(QGroupBoxH(QtGroupBox.Widget), @Str);
QtGroupBox.BoxLayout := QGridLayout_create(QtGroupBox.Widget);
QWidget_setLayout(QtGroupBox.Widget, QtGroupBox.BoxLayout);
QtGroupBox.ButtonGroup := TQtButtonGroup.Create(QObjectH(QtGroupBox.BoxLayout));
{QGridLayout don't know anything about TCustomRadioGroup Col count so initialize cols }
for i := 0 to TCustomRadioGroup(AWinControl).Columns - 1 do
begin
QGridLayout_setColumnMinimumWidth(QtGroupBox.BoxLayout, i, 32);
QGridLayout_setColumnStretch(QtGroupBox.BoxLayout, i, 0);
end;
{QGridLayout don't know anything about TCustomRadioGroup Row count so initialize rows }
for i := 0 to TCustomRadioGroup(AWinControl).Items.Count - 1 do
begin
QGridLayout_setRowMinimumHeight(QtGroupBox.BoxLayout, i, 22 {default height of radiobutton});
QGridLayout_setRowStretch(QtGroupBox.BoxLayout, i, 0);
end;
QtGroupBox.AttachEvents;
Result := THandle(QtGroupBox);
end;
{------------------------------------------------------------------------------
Method: TQtWSCustomRadioGroup.DestroyHandle
Params: None
Returns: Nothing
Releases allocated memory and resources
------------------------------------------------------------------------------}
class procedure TQtWSCustomRadioGroup.DestroyHandle(const AWinControl: TWinControl);
begin
if Assigned(TQtGroupBox(AWinControl.Handle).ButtonGroup) then
TQtGroupBox(AWinControl.Handle).ButtonGroup.Free;
if TQtGroupBox(AWinControl.Handle).BoxLayout <> NiL then
QGridLayout_destroy(TQtGroupBox(AWinControl.Handle).BoxLayout);
TQtGroupBox(AWinControl.Handle).Free;
AWinControl.Handle := 0;
end;
class procedure TQtWSCustomRadioGroup.ShowHide(const AWinControl: TWinControl);
var
i: Integer;
ATextWidth: Integer;
ATextHeight: Integer;
FM: QFontMetricsH;
Str: WideString;
begin
inherited ShowHide(AWinControl);
{without this we have invisible radio buttons}
{only this guarantee that our items are visible anytime ....}
for i := 0 to TRadioGroup(AWinControl).ComponentCount - 1 do
begin
if TRadioButton(AWinControl.Components[i]).Height = 0 then
begin
FM := QFontMetrics_create(QWidget_font(TQtRadioButton(TRadioButton(AWinControl.Components[i]).Handle).Widget));
try
Str := UTF8Encode(TRadioButton(AWinControl.Components[i]).Caption);
ATextWidth := QFontMetrics_width(FM, @Str, Length(Str));
ATextHeight := QFontMetrics_height(FM);
finally
QFontMetrics_destroy(FM);
end;
{ now, textwidth + default width of checkbox, default height
qt doesn't align well control with text size < 100}
if ATextWidth < 100 then
ATextWidth := 100;
TRadioButton(AWinControl.Components[i]).SetBounds(0, 0, ATextWidth + ATextHeight + 1, ATextHeight);
end;
end;
end;
{ TQtWSCustomCheckGroup }
{------------------------------------------------------------------------------
Method: TQtWSCustomCheckGroup.CreateHandle
Params: None
Returns: Nothing
Allocates memory and resources for the control and shows it
------------------------------------------------------------------------------}
class function TQtWSCustomCheckGroup.CreateHandle(const AWinControl: TWinControl;
const AParams: TCreateParams): TLCLIntfHandle;
var
QtGroupBox: TQtGroupBox;
Str: WideString;
i: Integer;
begin
QtGroupBox := TQtGroupBox.Create(AWinControl, AParams);
Str := UTF8Decode(AWinControl.Caption);
QGroupBox_setTitle(QGroupBoxH(QtGroupBox.Widget), @Str);
QtGroupBox.BoxLayout := QGridLayout_create(QtGroupBox.Widget);
QWidget_setLayout(QtGroupBox.Widget, QtGroupBox.BoxLayout);
QtGroupBox.ButtonGroup := TQtButtonGroup.Create(QObjectH(QtGroupBox.BoxLayout));
{QGridLayout don't know anything about TCustomCheckGroup Col count so initialize cols }
for i := 0 to TCustomCheckGroup(AWinControl).Columns - 1 do
begin
QGridLayout_setColumnMinimumWidth(QtGroupBox.BoxLayout, i, 32);
QGridLayout_setColumnStretch(QtGroupBox.BoxLayout, i, 0);
end;
{QGridLayout don't know anything about TCustomCheckGroup Row count so initialize rows }
for i := 0 to TCustomCheckGroup(AWinControl).Items.Count - 1 do
begin
QGridLayout_setRowMinimumHeight(QtGroupBox.BoxLayout, i, 22 {default height of checkbox});
QGridLayout_setRowStretch(QtGroupBox.BoxLayout, i, 0);
end;
QtGroupBox.AttachEvents;
Result := THandle(QtGroupBox);
end;
{------------------------------------------------------------------------------
Method: TQtWSCustomCheckGroup.DestroyHandle
Params: None
Returns: Nothing
Releases allocated memory and resources
------------------------------------------------------------------------------}
class procedure TQtWSCustomCheckGroup.DestroyHandle(const AWinControl: TWinControl);
begin
if Assigned(TQtGroupBox(AWinControl.Handle).ButtonGroup) then
TQtGroupBox(AWinControl.Handle).ButtonGroup.Free;
if TQtGroupBox(AWinControl.Handle).BoxLayout <> NiL then
QGridLayout_destroy(TQtGroupBox(AWinControl.Handle).BoxLayout);
TQtGroupBox(AWinControl.Handle).Free;
AWinControl.Handle := 0;
end;
class procedure TQtWSCustomCheckGroup.ShowHide(const AWinControl: TWinControl);
var
i: Integer;
ATextWidth: Integer;
ATextHeight: Integer;
FM: QFontMetricsH;
Str: WideString;
begin
{without this checkboxes are invisible}
inherited ShowHide(AWinControl);
{only this guarantee that our items are visible anytime ....}
for i := 0 to TCheckGroup(AWinControl).ComponentCount - 1 do
begin
if TCheckBox(AWinControl.Components[i]).Height = 0 then
begin
FM := QFontMetrics_create(QWidget_font(TQtCheckBox(TCheckBox(AWinControl.Components[i]).Handle).Widget));
try
Str := UTF8Encode(TCheckBox(AWinControl.Components[i]).Caption);
ATextWidth := QFontMetrics_width(FM, @Str, Length(Str));
ATextHeight := QFontMetrics_height(FM);
finally
QFontMetrics_destroy(FM);
end;
{ now, textwidth + default width of checkbox, default height
qt doesn't align well control with text size < 100}
if ATextWidth < 100 then
ATextWidth := 100;
TCheckBox(AWinControl.Components[i]).SetBounds(0, 0, ATextWidth + ATextHeight + 1, ATextHeight);
end;
end;
end;
initialization
////////////////////////////////////////////////////
// I M P O R T A N T
////////////////////////////////////////////////////
// To improve speed, register only classes
// which actually implement something
////////////////////////////////////////////////////
RegisterWSComponent(TCustomPage, TQtWSCustomPage);
RegisterWSComponent(TCustomNotebook, TQtWSCustomNotebook);
// RegisterWSComponent(TPage, TQtWSPage);
// RegisterWSComponent(TNotebook, TQtWSNotebook);
// RegisterWSComponent(TShape, TQtWSShape);
// RegisterWSComponent(TCustomSplitter, TQtWSCustomSplitter);
// RegisterWSComponent(TSplitter, TQtWSSplitter);
// RegisterWSComponent(TPaintBox, TQtWSPaintBox);
// RegisterWSComponent(TCustomImage, TQtWSCustomImage);
// RegisterWSComponent(TImage, TQtWSImage);
// RegisterWSComponent(TBevel, TQtWSBevel);
RegisterWSComponent(TCustomRadioGroup, TQtWSCustomRadioGroup);
// RegisterWSComponent(TRadioGroup, TQtWSRadioGroup);
RegisterWSComponent(TCustomCheckGroup, TQtWSCustomCheckGroup);
// RegisterWSComponent(TCheckGroup, TQtWSCheckGroup);
// RegisterWSComponent(TCustomLabeledEdit, TQtWSCustomLabeledEdit);
// RegisterWSComponent(TLabeledEdit, TQtWSLabeledEdit);
RegisterWSComponent(TCustomPanel, TQtWSCustomPanel);
// RegisterWSComponent(TPanel, TQtWSPanel);
////////////////////////////////////////////////////
end.