Always show options dropdown in TValueListEditor
Asked Answered
S

1

6

I'm trying to improve a GUI by reducing the amount of clicks needed to perform some actions. However, one VCL component that's bothering me is a TValueListEditor which contains a list of keys and values, all controlled by dropdowns. Selecting an options always requires three clicks, when only two are needed:

Bad

At this point in time, the topmost row has focus, and the value can be changed by using the dropdown (two clicks). However, when the user wants to edit a different key, he first has to change focus to that key before he can use the dropdown (three clicks).

Is there any way to show the dropdown arrow on all rows to prevent that extra click?

Here's a mockup example of what I want to achieve:

Good

Sindee answered 21/10, 2012 at 10:42 Comment(1)
may be better solution would be set row focus in onMouseMove event?Semanteme
P
8
uses
  Vcl.Themes;

type
  TValueListEditor = class(Vcl.ValEdit.TValueListEditor)
  private
    procedure DrawDropDownButton(ACol, ARow: Integer; ARect: TRect;
      AState: TGridDrawState);
    function MouseOverButton(X: Integer): Boolean;
  protected
    procedure DrawCell(ACol, ARow: Integer; ARect: TRect;
      AState: TGridDrawState); override;
    procedure DrawCellHighlight(const ARect: TRect; AState: TGridDrawState;
      ACol, ARow: Integer); override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X,
      Y: Integer); override;
  end;

{ TValueListEditor }

type
  TInplaceEditListAccess = class(Vcl.Grids.TInplaceEditList);

procedure TValueListEditor.DrawCell(ACol, ARow: Integer; ARect: TRect;
  AState: TGridDrawState);
begin
  inherited DrawCell(ACol, ARow, ARect, AState);
  DrawDropDownButton(ACol, ARow, ARect, AState);
end;

procedure TValueListEditor.DrawCellHighlight(const ARect: TRect;
  AState: TGridDrawState; ACol, ARow: Integer);
var
  R: TRect;
begin
  R := ARect;
  if ItemProps[ARow - FixedRows].HasPickList then
    Dec(R.Right, EditList.ButtonWidth);
  inherited DrawCellHighLight(R, AState, ACol, ARow);
  DrawDropDownButton(ACol, ARow, ARect, AState);
end;

procedure TValueListEditor.DrawDropDownButton(ACol, ARow: Integer;
  ARect: TRect; AState: TGridDrawState);
var
  Details: TThemedElementDetails;
begin
  if (ACol = 1) and (ARow >= FixedRows) and not (gdFocused in AState) and
    ItemProps[ARow - FixedRows].HasPickList then
  begin
    ARect.Left := ARect.Right - EditList.ButtonWidth;
    Details := StyleServices.GetElementDetails(tgDropDownButtonNormal);
    StyleServices.DrawElement(Canvas.Handle, Details, ARect);
  end;
end;

procedure TValueListEditor.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
var
  ACol: Integer;
  ARow: Integer;
begin
  inherited MouseDown(Button, Shift, X, Y);
  MouseToCell(X, Y, ACol, ARow);
  if (Button = mbLeft) and (ARow > FixedRows) and
    ItemProps[ARow - FixedRows].HasPickList and
    not EditList.ListVisible and MouseOverButton(X) then
  begin
    EditorMode := True;
    TInplaceEditListAccess(EditList).DropDown;
  end;
end;

function TValueListEditor.MouseOverButton(X: Integer): Boolean;
begin
  Result := (UseRightToLeftAlignment and (X < EditList.ButtonWidth)) or
    (not UseRightToLeftAlignment and (X > ClientWidth - EditList.ButtonWidth));
end;

enter image description here

Polash answered 21/10, 2012 at 23:50 Comment(3)
That seems to work perfectly fine. One side note though (some detail I forgot to mention): I use Delphi 7 and it declares the theme services as 'ThemeServices' instead of 'StyleServices', it does not expose DrawCellHighlight and it defines the dropdown arrow as 'tcDropDownButtonNormal' but apart from that, this is an excellent solution.Sindee
May I suggest an improvement? At least in Delphi 7, when this component is added to the palette and used to design forms, EditList might not always be assigned, resulting in quite a bit of error spew. I suggest adding checks for 'Assigned(EditList)' to any place that makes use of it.Sindee
@Sindee I didn't design nor test it to be installed as a component. But you can/may change it yourself here. Maybe add a corresponding property too then?Polash

© 2022 - 2024 — McMap. All rights reserved.