Tiburón Preview: TButtonedEdit

As I mentioned earlier I’ll be posting a series of previews of new VCL features. First up is the all new TButtonedEdit component:  

  

TButtonedEdit preview     

    

Derived from TEdit, it provides embedded buttons that can optionally drop down a popupmenu (as seen above). We’ve used this new component in the Tiburón IDE, one example is shown here in a post by Chris Bensen.

    

Posted by Seppy Bloom on July 18th, 2008 under Uncategorized



14 Responses to “Tiburón Preview: TButtonedEdit”

  1. Lee Grissom Says:

    Hmm, looking at the screen shot, it seems that you guys went with the approach of hard-coding "Left" and "Right" buttons. It would have been wiser to have a "Buttons" collection, with location as a enumeration property. That way, you can have more than just two buttons, and you can place the buttons on either side. Or, if you really only want to limit the user to having two buttons (which I’m fine with), you should have added an enumeration to anchor the buttons to either side of the control. Maybe all my assumptions are wrong.

  2. Jan Derk Says:

    Lee you are right. A generic Buttons list would have been much smarter. It is what DevExpress has done years ago. DevExpress allows you to have unlimited buttons on the left and right.

    Good developers always think how they can make things generic to allow future extensions. Mediocre ones just start with Button1, Button2 properties and add Button3 when somebody asks for more.

  3. Roddy Says:

    Don’t stop there. Instead of a buttons collection, have a controls collection, then you can have many separate editable fields within your TButtonedEdit, or nest TButtonEdits within each other.

    Good grief. What possible use can you (Lee, Jan) see in a well-designed UI for more than two buttons in a single TButtonedEdit?

    IMO, trying to accomodate a load of unnecessary features for future "potential expansion" that users are most unlikely to ever need is /not/ a sign of a good programmer.

  4. Roddy Says:

    Oops. The "joke" tags on the first sentence of my last post got eaten…

  5. m. Th. Says:

    Thanks Seppy for blogging again! It’s always an encouraging sign when we see innovation attempts in VCL. Thanks again! But can I dare to make some small comments?…

    +1 at Lee’s observations.

    Also, of course TButtonedEdit should be derived from TCustomButtonedEdit which should be derived from TCustomEdit, isn’t? ;-) …derived directly from TEdit it’s a little bit harsh for my eyes… but perhaps I’m wrong?

    Again, in your screen shot is to be seen NumbersOnly = False. Guys, why I have the feeling that from some years you design the VCL in a somewhat ‘quick-time’ mode? I’d rather want to see more careful designs. For ex. just have a look at TJvValidateEdit (from JEDI) (well, this because is free & open sourced - of course I will not speak now about commercial alternatives of NumbersOnly=True/False). In JVCL, instead of having NumbersOnly: boolean; they have:

    TJvValidateEdit = class(TJvCustomValidateEdit)

    where

    TJvCustomValidateEdit = class(TJvCustomEdit)

    … //only listed here a part of the data validation engine

    property CheckChars: string read FCheckChars write SetCheckChars
    stored IsCheckCharsStored;
    property TrimDecimals: Boolean read FTrimDecimals write SetTrimDecimals;
    property DecimalPlaces: Cardinal read FDecimalPlaces write SetDecimalPlaces;
    property DisplayFormat: TJvValidateEditDisplayFormat read FDisplayFormat
    write SetDisplayFormat;
    property EditText: string read GetEditText write SetEditText;
    property HasMaxValue: Boolean read FHasMaxValue write SetHasMaxValue;
    property HasMinValue: Boolean read FHasMinValue write SetHasMinValue;
    property MaxValue: Double read FMaxValue write SetMaxValue;
    property MinValue: Double read FMinValue write SetMinValue;
    property OnCustomValidate: TJvCustomTextValidateEvent
    read FOnCustomValidate write FOnCustomValidate;
    property OnValueChanged: TNotifyEvent read FOnValueChanged write FOnValueChanged;
    property Value: Variant read GetValue write SetValue stored False;
    property AllowEmpty: Boolean read FAllowEmpty write FAllowEmpty;
    property ZeroEmpty: Boolean read FZeroEmpty write SetZeroEmpty;
    property DisplayPrefix: string read FDisplayPrefix write SetDisplayPrefix;
    property DisplaySuffix: string read FDisplaySuffix write SetDisplaySuffix;
    property CriticalPoints: TJvValidateEditCriticalPoints read FCriticalPoints
    write FCriticalPoints;
    property AutoAlignment: Boolean read FAutoAlignment write FAutoAlignment;

    end;

    where

    TJvValidateEditDisplayFormat = (dfAlphabetic, dfAlphaNumeric, dfBinary,
    dfCheckChars, dfCurrency, dfCustom, dfFloat, dfFloatGeneral, dfHex, dfInteger,
    dfNonCheckChars, dfNone, dfOctal, dfPercent, dfScientific, dfYear);

    //hummm…. a little bit different compared with NumbersOnly, isn’t?

    TJvValidateEditCriticalPoints = class(TPersistent)
    …//an entire class for this. Have a look.

    Perhaps the core to understand the Critical Points engine is…

    TJvValidateEditCriticalPointsCheck = (cpNone, cpMinValue, cpMaxValue, cpBoth);

    …and did I mention that it can work as data-aware and non-data-aware component ? (see ‘DataConnector’ property)

    FTR, the above unit was started in 2003 and last touched 2 (two) years ago:
    // $Id: JvValidateEdit.pas 11040 2006-11-25 15:49:51Z marquardt $

    …by Robert Marquardt (R.I.P.)

    …And comparing the above ol’ comp’ with the ‘brand new TButtonedEdit’… oh, well… But perhaps if you’ll made a TCustomButtonedEdit (as I stated above) the perhaps the others (including JEDI guys) will leverage it, even if it has ‘closed’/inflexible properties like NumbersOnly.

    OTOH, imho, perhaps its better to ask the community for feedback when you’ll do such implementations, because you never know, perhaps someone from the crowd will *might* give you some ideas… :-)

    Anyway, many thanks for blogging again. Very welcomed. And please don’t take to hard my post. It was meant solely to help you. Because, you see, VCL is something on the foundation on which we all build. That’s why, perhaps, we must cooperate.

    HTH & just my 2c,

    m. Th.

  6. m. Th. Says:

    …me again. Sorry for double posting. A neat usage case for more than two buttons: In component pallette you can have three buttons:

    1. (located to the left) Reset filter
    2. (1st to right) MRU list of components (QC #55404) - same with ‘Start - My Documents’ in WinXP
    3. (2nd to right) "Most used components" menu (QC #49791) - same with the left panel of Start menu in WinXP.

    As an aside unfortunately ’someone’ marked 2.) and 3.) as duplicates in QC. This is not the case and also can cause problems in QC (because it cannot support marking duplicates two open reports).

    HTH

  7. Kryvich Says:

    m. Th. -

    I disagree with you in part: 2. and 3. have to be independant buttons with menus on the palette’s toolbar. That functionality refers to the tool palette in whole, not to the filter edit.

  8. m. Th. Says:

    @ Kryvich -
    Yep. Stand corrected. :-)
    …but the main point is: Will they do it?

  9. nix Says:

    I see the control retrieves the glyph from a TImageList. Do you have any buttons (e.g. TBitBtn) that support ImageLists yet?

  10. Seppy Bloom Says:

    m. Th.: TButtonedEdit does descend from TCustomButtonedEdit which descends from TCustomEdit. Sorry for not be more clear about that.

    Nix: Stay tuned

  11. Chris Bensen Says:

    TButtonedEdit = class(TCustomButtonedEdit)

  12. m. Th. Says:

    Seppy & Chris:

    Thanks a lot! No probl’m Seppy :-)
    Also, I wasn’t clear myself :-). Clarifications:

    1. Ok, if you want to implement an entire validation engine (but the kitchen sink) it would be very nice, but it’s up to you, - we’ll be, of course, glad to have it ;-) but my point was to ‘borrow’ from JEDI /at least/ a DisplayFormat: TDisplayFormat property (ie. something to build/extend upon) which will expose, in fact the ‘Format’ family of functions, something like:

    case FDisplayFormat of
    dfNumber: FDisplayText:=Format(…);
    dfMoney: FDisplayText:=Format(…);
    dfHex: FDisplayText:=IntToHex(IntToStrDef(…));

    //etc.
    end;

    …and for Tiburon to support only the straightforward ones.

    For the input validation, and, of course, for an another gazillion of needs, a regexp engine would be desperately needed. But in the mean time we can live with a
    try
    format(…); //in fact the above ‘case’ engine
    except
    ShowMessage(’Invalid input’);
    end;

    Imho, in 2008 A.D. we need more formatting options than TMaskEdit.

    2. "Will they do it?" - I meant the Component Palette enhancements first - MRU etc. (hint, hint Chris ;-) ) and in a 2ndary plane the TEditButtonsCollection (or whatever).

    To be continued… See my other posts which follow ;-)

  13. m. Th. Says:

    …Thinking a little bit more about this component, imho, one of his main usages would be in layout engines (TFlowPanel, TGridPanel, grids (wake-up!), multi-column trees (see http://tinyurl.com/2jmlhh for the definitive solution in this regard). WRT this, did you use InsertSubcomponent? Because the other compound component made in the same manner (TLabeledEdit) causes AV and other nasty problems in such situations (for ex. see QC #57611, #57404, #35104, #29394 etc.). As an aside, perhaps for compound components you can build a wizard for the users to use the more flexible approach of TFrame? - for full details see QC #50234.

  14. m. Th. Says:

    …well, this is a painful one (for us).
    By far, AFAIS, I, you and many others will use the button(s) from this component to display popups. But why limit us to TPopupMenu? We (oh, wait, you) can very easy implement very small change/addition in code to allow us to use any /form/ as a popup form. (See QC #55762). How to do it? (I try to be as clear as I can, if you (or someone) don’t understand something please feel free to ask - we use it from many years now and perhaps my description is a little bit convoluted).

    The algorithm is like this:

    - a.) Have a form designed visually
    - b.) ‘Connect’ the form to the TButtonedEdit (this mean that on app startup the form is ‘fixed’ a little ie. Visible:=False)
    - c.) When the button is pressed we have:
    -c.1) Hook the main message queue in order to auto-close the ‘popup’ when the component looses focus, window is moved etc. (very simple code, available upon request)

    -c.2) call a simple tiling procedure (pretty similar to TPopupMenu.Popup) - will align the form near to the button. Our poor-man ‘engine’ (which served us very well in last 5-6 years) has the declaration:

    function TryToShowCtrlPopup(aCtrl, aMaster: TControl; aCorner: TOblicDir): boolean;

    //very simple code snipped

    - with -
    type
    TOblicDir = (odSE, odSW, odNE, odNW);
    //— where N=north, S=shouth, W=west, E=east

    …Imho this is very simple and straightforward. I can send you the code if you’re willing to implement it. But why I said that this is ‘a painful one’ (for us)? Because all the above algorithm becomes suddenly very hard to deal with because 2 (I mean /two/) lines of code is missing from VCL. You forget to add in TForm’s interface a procedure to show the form without activating it. Doing this from outside it doesn’t work (I don’t remember now why - ask Peter Bellow - I just remember that we tried *a lot*) so we must do something like…

    TPopupForm = class (TForm)
    public
    procedure ShowNA;
    end;

    { TPopupForm }

    procedure TPopupForm.ShowNA;
    begin
    ShowWindow(Handle, SW_SHOWNA);
    Visible:=True;
    end;

    …which blows out the entire idea of a general popup algorithm for forms and (of course) the possibility to visually design them. Of course we tried: ShowWindow(ConnectedForm.Handle, SW_SHOWNA); ConnectedForm.Visible:=True; but (as I said) it doesn’t work.

    Imho, with a very small amount of effort from your side, you’ll open a new broad range of possibilities for us, developers.

    Also, as an aside…
    1.) ShowNA procedure would be useful not only in the above case
    2.) as you can see above, you can made the above form popup engine loosely coupled to a TControl (perhaps you can implement it as an invisible control = class(TComponent)) in order to have form popups not only for TButtonedEdit but also for the entire range of buttons, panels, labels, images etc. etc.)

    Just my 2c & HTH,

    m. Th.

Leave a Comment

rss feed
technorati fav


July 2008
M T W T F S S
« Jul   Aug »
 123456
78910111213
14151617181920
21222324252627
28293031  

Meta:


 

Bad Behavior has blocked 34 access attempts in the last 7 days.

Close