mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-08 06:12:43 +02:00
LCL: Improve TToolButton drop down behavior. Issue #28231, patch from Ondrej Pokorny.
git-svn-id: trunk@49465 -
This commit is contained in:
parent
16c48dc400
commit
7cf21da4da
@ -1990,6 +1990,7 @@ type
|
|||||||
FToolButtonFlags: TToolButtonFlags;
|
FToolButtonFlags: TToolButtonFlags;
|
||||||
FUpdateCount: Integer;
|
FUpdateCount: Integer;
|
||||||
FWrap: Boolean;
|
FWrap: Boolean;
|
||||||
|
FLastDropDownTick: QWord;
|
||||||
procedure GetGroupBounds(var StartIndex, EndIndex: integer);
|
procedure GetGroupBounds(var StartIndex, EndIndex: integer);
|
||||||
function GetIndex: Integer;
|
function GetIndex: Integer;
|
||||||
function GetTextSize: TSize;
|
function GetTextSize: TSize;
|
||||||
|
@ -58,14 +58,31 @@ end;
|
|||||||
|
|
||||||
procedure TToolButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
procedure TToolButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
||||||
X, Y: Integer);
|
X, Y: Integer);
|
||||||
|
|
||||||
|
procedure SendButtonUpMsg;
|
||||||
|
var
|
||||||
|
msg: TLMMouse;
|
||||||
|
pt: TPoint;
|
||||||
|
begin
|
||||||
|
FillChar({%H-}msg, SizeOf(msg), 0);
|
||||||
|
msg.Msg:=LM_LBUTTONUP;
|
||||||
|
pt := ScreenToClient(Mouse.CursorPos);
|
||||||
|
msg.XPos:=pt.X;
|
||||||
|
msg.YPos:=pt.Y;
|
||||||
|
WndProc(TLMessage(msg));
|
||||||
|
end;
|
||||||
var
|
var
|
||||||
NewFlags: TToolButtonFlags;
|
NewFlags: TToolButtonFlags;
|
||||||
begin
|
begin
|
||||||
//debugln(['TToolButton.MouseDown ',DbgSName(Self)]);
|
//debugln(['TToolButton.MouseDown ',DbgSName(Self)]);
|
||||||
|
SetMouseInControl(True);
|
||||||
NewFlags := FToolButtonFlags - [tbfPressed, tbfArrowPressed];
|
NewFlags := FToolButtonFlags - [tbfPressed, tbfArrowPressed];
|
||||||
if (Button = mbLeft) then
|
if (Button = mbLeft) then
|
||||||
begin
|
begin
|
||||||
if Enabled then
|
//use some threshold to decide if the DropdownMenu should be opened again.
|
||||||
|
// When no DropdownMenu is assigned, FLastDropDownTick is always 0
|
||||||
|
// therefore the condition is always met.
|
||||||
|
if Enabled and not(GetTickCount64 < FLastDropDownTick + 100) then
|
||||||
begin
|
begin
|
||||||
if (Style = tbsDropDown) and (FToolBar <> nil) and (X > ClientWidth - FToolBar.FDropDownWidth) then
|
if (Style = tbsDropDown) and (FToolBar <> nil) and (X > ClientWidth - FToolBar.FDropDownWidth) then
|
||||||
Include(NewFlags, tbfArrowPressed)
|
Include(NewFlags, tbfArrowPressed)
|
||||||
@ -81,17 +98,33 @@ begin
|
|||||||
|
|
||||||
inherited MouseDown(Button, Shift, X, Y);
|
inherited MouseDown(Button, Shift, X, Y);
|
||||||
|
|
||||||
if (Style = tbsDropDown) and (Button = mbLeft) and Enabled then
|
FLastDropDownTick := 0;
|
||||||
|
if (Button = mbLeft) and Enabled and
|
||||||
|
(Style in [tbsButton, tbsDropDown]) then
|
||||||
begin
|
begin
|
||||||
if NewFlags * [tbfArrowPressed] = [] then
|
if ((Style = tbsButton) and (tbfPressed in NewFlags) or
|
||||||
Down := True;
|
(Style = tbsDropDown) and (tbfArrowPressed in NewFlags)) and
|
||||||
|
CheckMenuDropdown then
|
||||||
|
begin
|
||||||
|
FLastDropDownTick := GetTickCount64;
|
||||||
|
|
||||||
|
//because we show the DropdownMenu in MouseDown, we have to send
|
||||||
|
// LM_LBUTTONUP manually to make it work in all widgetsets!
|
||||||
|
// Some widgetsets work without it (e.g. win32) but some don't (e.g. carbon).
|
||||||
|
SendButtonUpMsg;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
if (Style = tbsDropDown) and
|
||||||
|
(NewFlags * [tbfArrowPressed, tbfPressed] = [tbfPressed])
|
||||||
|
then
|
||||||
|
Down := True;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TToolButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
procedure TToolButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
||||||
X, Y: Integer);
|
X, Y: Integer);
|
||||||
var
|
var
|
||||||
DropDownMenuDropped: Boolean;
|
|
||||||
Pressed: Boolean;
|
Pressed: Boolean;
|
||||||
Pt: TPoint;
|
Pt: TPoint;
|
||||||
begin
|
begin
|
||||||
@ -114,26 +147,24 @@ begin
|
|||||||
if not PtInRect(Rect(0,0,Width,Height), Pt) then
|
if not PtInRect(Rect(0,0,Width,Height), Pt) then
|
||||||
SetMouseInControl(false);
|
SetMouseInControl(false);
|
||||||
end;
|
end;
|
||||||
DropDownMenuDropped := False;
|
|
||||||
//DebugLn('TToolButton.MouseUp ',Name,':',ClassName,' ',Style=tbsCheck);
|
|
||||||
if (Style in [tbsButton, tbsDropDown]) then
|
if (Style in [tbsButton, tbsDropDown]) then
|
||||||
begin
|
|
||||||
if (FToolBar <> nil) and FMouseInControl and
|
|
||||||
((Style = tbsButton) or (X > ClientWidth - FToolBar.FDropDownWidth)) then
|
|
||||||
DropDownMenuDropped := CheckMenuDropdown;
|
|
||||||
Down := False;
|
Down := False;
|
||||||
end;
|
//button is pressed, but DropdownMenu was not shown
|
||||||
|
if FMouseInControl and (FLastDropDownTick = 0) and Pressed then
|
||||||
//debugln(['TToolButton.MouseUp ',DbgSName(Self),' FMouseInControl=',FMouseInControl,' DropDownMenuDropped=',DropDownMenuDropped]);
|
|
||||||
if FMouseInControl and not DropDownMenuDropped then
|
|
||||||
begin
|
begin
|
||||||
if (Style = tbsCheck) then
|
if (Style = tbsCheck) then
|
||||||
Down := not Down;
|
Down := not Down;
|
||||||
if Pressed then
|
Click;
|
||||||
Click;
|
|
||||||
|
//Mouse position can have changed after click (e.g. through a modal dialog)
|
||||||
|
if FMouseInControl then
|
||||||
|
begin
|
||||||
|
Pt := ScreenToClient(Mouse.CursorPos);
|
||||||
|
if not PtInRect(Rect(0,0,Width,Height), Pt) then
|
||||||
|
SetMouseInControl(false);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
Invalidate;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TToolButton.Notification(AComponent: TComponent;
|
procedure TToolButton.Notification(AComponent: TComponent;
|
||||||
@ -498,13 +529,12 @@ procedure TToolButton.MouseLeave;
|
|||||||
begin
|
begin
|
||||||
// DebugLn('TToolButton.MouseLeave ',Name);
|
// DebugLn('TToolButton.MouseLeave ',Name);
|
||||||
inherited MouseLeave;
|
inherited MouseLeave;
|
||||||
SetMouseInControl(false);
|
|
||||||
if (not MouseCapture) and ([tbfPressed, tbfArrowPressed] * FToolButtonFlags <> []) then
|
if (not MouseCapture) and ([tbfPressed, tbfArrowPressed] * FToolButtonFlags <> []) then
|
||||||
begin
|
begin
|
||||||
Exclude(FToolButtonFlags, tbfPressed);
|
Exclude(FToolButtonFlags, tbfPressed);
|
||||||
Exclude(FToolButtonFlags, tbfArrowPressed);
|
Exclude(FToolButtonFlags, tbfArrowPressed);
|
||||||
Invalidate;
|
|
||||||
end;
|
end;
|
||||||
|
SetMouseInControl(false);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TToolButton.SetDown(Value: Boolean);
|
procedure TToolButton.SetDown(Value: Boolean);
|
||||||
|
Loading…
Reference in New Issue
Block a user