FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister   ProfileProfile   Log inLog in 


Correction of stiff dialog box of vpiCommonDialogs::ask predicate

Post new topic   Reply to topic    discuss.visual-prolog.com Forum Index -> Visual Prolog Tips & Samples
View previous topic :: View next topic  
Author Message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 1 Apr 2016 7:31    Post subject: Correction of stiff dialog box of vpiCommonDialogs::ask predicate Reply with quote

Symptom №1:
The original dialog shows only three buttons. The others are beyond the client area of the window.
Symptom №2:
The sizes of push buttons are fixed. Long words appear truncated.

The essence of my correction is:


class facts
    ask_result:integer := 0.
    default: positive :=0.
    right: integer:=265. %<== Fact for determination of the necessary width.
    bottom:integer:=0. %<== Fact for determination of the necessary bottom.
clauses
    ask(Title, Prompt, ButtonTitlesList,Default) = ask_result :-
        L=list::length(ButtonTitlesList),
        bottom:=40+20*L,
        Parent=vpi::getParentWindow(),
        ParentFont=winGetFont(Parent),
        fontGetAttrs(ParentFont,_,_)=FontName,
        Static=ctl(
            wdef(wc_Text,rct(2,2,152,20*L),
                Prompt,u_DlgBase),10001,[wsf_AlignCenter]),
        Flags=[wsf_Group,wsf_TabStop,wsf_AlignCenter ],
        FlagsD=[wsf_Default|Flags],
        Ctl_List=
            [
            CtlI
            ||
            I=std::fromTo(0,L-1),
            if I=Default then FlagsI=FlagsD else FLagsI=Flags end if,
            ButtonTitle=list::nth(convert(positive,I),ButtonTitlesList),
            % 2016.04.01. These lines determine the necessary with and height of the buttons based on the estimated text extent.
            winGetTextExtent(Parent,ButtonTitle,W,H),
            Right=math::max(210,165+W),
            Bottom=17+math::max(H+5,20)*I,
            right:=math::max(Right,right),
            bottom:=math::max(bottom,Bottom),
            CtlI=ctl(
                    wdef(wc_PushButton,rct(155,5+20*I,Right,Bottom),ButtonTitle,u_DlgBase),
                    I,FlagsI)
            ],
        % 2016.04.01. Final stretch of the window
        RCT=rct(50,40,right+60,bottom+10),
        FontDef=dlgFont(
            wdef(wd_Modal,RCT,Title,u_DlgBase),FontName,8,[wsf_TitleBar]),
        default:=math::min(L-1,Default),
        _ = vpi::winCreateDynDialog(Parent,[FontDef,Static|Ctl_List],
            dlg_ask_eh,gui_api::lNull).

Example usage: Validation of integer controls:


% 2016.03.29. Validation of integer controls.
validateIntegerControl(IC) = control::contentsInvalid(Source,FocusControl,Msg) :-
    IC:validate()=control::contentsInvalid(Source,FocusControl,Msg),
    FocusControl:setFocus(),
    Resp=extendedCommonDialogs::ask(substitute,Msg,value_choice_list,1),
    substituteSpecialInteger(IC,Resp),
    !.
validateIntegerControl(IC) = control::contentsOK :-
    retractAll(previousInteger(IC,_)),
    assertz(previousInteger(IC,IC:getInteger())).




Extended ask dialog.png
 Description:
Screenshot of the extended ask dialog appearing in case invalid fill of an integer control.
 Filesize:  7.23 KB
 Viewed:  2960 Time(s)

Extended ask dialog.png



ExtendedCommonDialogs.pro
 Description:
Clauses

Download
 Filename:  ExtendedCommonDialogs.pro
 Filesize:  2.28 KB
 Downloaded:  135 Time(s)


ExtendedCommonDialogs.cl
 Description:
Class predicates

Download
 Filename:  ExtendedCommonDialogs.cl
 Filesize:  312 Bytes
 Downloaded:  135 Time(s)


_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 2 Apr 2016 22:24    Post subject: Reply with quote

Very nice, Ferenc! That will save creating a few custom Ask dialogs.

I have a suggestion for an enhancement: Change the PromptString to a string_list equal in length (or maybe not) to the number of buttons, then make the members of the PromptList line up horizontally with the buttons and right-align the text to the longest member of the PromptList.

This would provide an opportunity to give the user more information on the response to selecting different buttons.

Attached is a test of your Ask embedding "\n\n" in the PromptString, so you can get an idea of what I mean.



FerencNagyAskBox.jpg
 Description:
Mock-up multi-line comment using nn
 Filesize:  39.41 KB
 Viewed:  2948 Time(s)

FerencNagyAskBox.jpg


Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 3 Apr 2016 14:19    Post subject: Reply with quote

Ferenc,
The buttons and the static text controls are not using the same font as the dialog Title font. I don't understand why that is happening when I look at your code.

Also, perhaps the button size should be calculated before entering the control definition loop (assuming that you intended all the buttons to be of the same size). I realize I did give your dialog a "stress test" with my test values! Smile
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 9 Apr 2016 17:54    Post subject: Reply with quote

Ferenc's idea was so useful that I decided to extend and modify it to make it even more broadly usable.

Code modifications:
May use either the default dialog font or that of the Parent window.
Fontsize follows that of the Parent window or default font, not hard coded.
Button width is adjusted using DBU scaling.
Move button width adjustment now sets all buttuns to same width.
Change Prompt alignment to left alignment (will word wrap long text within limits of text box).
Align prompt text and top button.
The magic numbers in the code are changed to constants for easier layout adjustment.

Functional extension predicates:

    askRespNum : ( string Title, string Prompt, string* ButtonTitlesList, positive Default0, boolean UseParentFont ) -> integer Picked0.
        % Returns the 0-based index of the selected button.
        % Cannot fail.

    askToken : ( string Title, string Prompt, string* ButtonTitlesList, positive Default0, boolean UseParentFont  ) -> string PickedFrontToken determ.
        % Return front token of selected label,
        % FAILs if label does not return a token (e.g. Label is all white space).

    askString: ( string Title, string Prompt, string* ButtonTitlesList, positive Default0, boolean UseParentFont  ) -> string PickedLabel.
        % Return the complete string of the selected label.
        % Cannot fail.

I have no doubt that some of you can improve on this. All input is appreciated. Very Happy



AskPlus Dialog Using ParentWin Font.jpg
 Description:
 Filesize:  110.19 KB
 Viewed:  2923 Time(s)

AskPlus Dialog Using ParentWin Font.jpg



AskPlus Dialog Using Default Font.jpg
 Description:
 Filesize:  97.63 KB
 Viewed:  2923 Time(s)

AskPlus Dialog Using Default Font.jpg



askPlus.cl
 Description:
Updated 2016-04-24

Download
 Filename:  askPlus.cl
 Filesize:  3.13 KB
 Downloaded:  142 Time(s)


askPlus.pro
 Description:
Updated 2016-04-24

Download
 Filename:  askPlus.pro
 Filesize:  6.69 KB
 Downloaded:  141 Time(s)



Last edited by Harrison Pratt on 24 Apr 2016 18:44; edited 1 time in total
Back to top
View user's profile Send private message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 24 Apr 2016 7:50    Post subject: Reply with quote

Harrison,
Thank you for the suggestions.

_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 24 Apr 2016 9:41    Post subject: Reply with quote

Harrison,

I use the font of the parent window.
This is "Andale Mono" because of two reasons.
1) I have build this extended ask dialog into a program which is based on a Russian program. Tahoma was recommended for Russian dialogs in this forum.
2) I can guess better the lookout of the dialogs if their font is monospace than they are based on a proportional font.

I show the essential lines dealing with fonts in my dialog creation below.


Parent=vpi::getParentWindow(),
        ParentFont=winGetFont(Parent),
        fontGetAttrs(ParentFont,_,_)=FontName,
% SNIP
 FontDef=dlgFont(
            wdef(wd_Modal,RCT,Title,u_DlgBase),FontName,8,[wsf_TitleBar]),
        default:=math::min(L-1,Default),
        _ = vpi::winCreateDynDialog(Parent,[FontDef,Static|Ctl_List],
            dlg_ask_eh,gui_api::lNull).

You are absolute right that the buttons should have equal width or at least multiplies of a minimal one.

I guess that your askString and askToken procedures are useful. Branching on strings or tokens is more stable as of order numbers of choices against accidental reordering of button titles list and deleting, inserting - not appending - a new choice into them.
Button titles may contain disturbing ampersand characters (denoting the next underscored character).
Here is my general solution to remove them.

predicates
     % Delete ampersand from the text of a control.
    deleteAmpersand:(control) -> string procedure.

clauses
    % Delete ampersand from the text of a control.
    deleteAmpersand(Control) = replaceFirst(Control:getText(),"&","",caseInsensitive).


_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 24 Apr 2016 12:55    Post subject: Reply with quote

Frank,

Thank you for your comments which help me appreciate your dialog design challenges. I struggled a while with the button width issue until finally remembering that dialog base unit calculation is required (well, not strictly required but useful) in dynamic generated dialogs. I'd used it in VIP 5.2, forgot it and found it again in the 5.2 manual.

I decided to left_align the text box so I could display a multi-line prompt, but gave up on aligning prompt text lines with buttons as something not likely to be very useful in practice.

Your reminder about embedded '&' is good-- will fix that now instead of in the middle of a big project!

I expect I will use askToken most often and am not certain when I'll need askString, but left it accessible just in case.

Thanks for your help!
Harrison Very Happy
Back to top
View user's profile Send private message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 24 Apr 2016 16:17    Post subject: Reply with quote

Harrison,
If you prefer askToken then take care of different and informative first tokens of the button titles.

_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 24 Apr 2016 17:47    Post subject: Reply with quote

Harrison,
My latest changes in my extended ask dialog:
1) Introduction of class properties triggering the size of the buttons and the vertical gap among them.


extendedCommonDialogs::height_factor :=1.25,
extendedCommonDialogs::height_plus:= 5,
extendedCommonDialogs::vertical_gap:=10,

Their defaults:


class facts - height_correction % 2016.04.24.
    % Height factor.
   height_factor : real  :=1.5.
   % Fixed additon to text height.
   height_plus  : positive:= 5.
    % Vertical gap between buttons.
   vertical_gap : positive := 10.

Usage of these parameters are shown in the attached Windiff reports.



Equal width and higher buttons with centered titles.PNG
 Description:
 Filesize:  8.78 KB
 Viewed:  2859 Time(s)

Equal width and higher buttons with centered titles.PNG



mod_of_pro.htm
 Description:
Modification of the pro file.

Download
 Filename:  mod_of_pro.htm
 Filesize:  33.43 KB
 Downloaded:  124 Time(s)


mod_of_cl.htm
 Description:
Modification of the cl file.

Download
 Filename:  mod_of_cl.htm
 Filesize:  8.98 KB
 Downloaded:  121 Time(s)


_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 24 Apr 2016 18:20    Post subject: Re: Reply with quote

Ferenc Nagy wrote:
Harrison,
If you prefer askToken then take care of different and informative first tokens of the button titles.

Do you mean to say that it is the responsibility of the developer to ensure that the frontTokens of all the button titles are unique? If not, I don't understand your meaning.
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 24 Apr 2016 18:53    Post subject: Re: Reply with quote

Frank,

Good idea! Eventually that will be needed.

I updated my code to reflect your suggestion about removing the '&' accelerator character. Smile

Harrison



Ferenc Nagy wrote:
Harrison,
My latest changes in my extended ask dialog:
1) Introduction of class properties triggering the size of the buttons and the vertical gap among them.


extendedCommonDialogs::height_factor :=1.25,
extendedCommonDialogs::height_plus:= 5,
extendedCommonDialogs::vertical_gap:=10,


Back to top
View user's profile Send private message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 25 Apr 2016 6:45    Post subject: Reply with quote

Harrison:
Quote:
Do you mean to say that it is the responsibility of the developer to ensure that the frontTokens of all the button titles are unique?

Yes, I have thought so. That is why I recommended the removal of the ampersand before the characters to be underscored on the screen.
Imagine that button1 control has text "Draw &Logarithmic Plot" and button3 has text "Draw &Linear Plot", respectively.
What is their front token? The same "Draw". I do not know whether '&' character is a token or not. The second or the third token of the button texts are different.

Let me return to my latest corrections in my version of extended ask dialog.
Earlier I had positioned the buttons vertically using a linear function their index on their list multiplied by a fixed factor added to a fixed starting value.
The current version adds a gap to the bottom line of the current button rectangle and uses the result as the top line of the next button rectangle.

_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 25 Apr 2016 13:13    Post subject: Reply with quote

I understand. That's why I wrote 3 variants of the askXXX predicates.
The '&' is a token delimiter in both alphabetic string and numeric strings. I think that relying on the '&' to tokenize is risky because it would be easy to later change the accelerator character and forget that you were using it to tokenize the string response. Your caution about stripping the first '&' is wise.
Back to top
View user's profile Send private message
Ferenc Nagy



Hungary
Joined: 24 Apr 2007
Posts: 378

PostPosted: 12 May 2016 16:39    Post subject: Reply with quote

Harrison,
I have two new ideas:
1) Define positive constants with informative names in the module where you evaluate the result of the extended ask dialog.


constants
    substitute_previous =0.
    substitute_default =1.
    substitute_minimal =2.
    substitute_maximal =3.

The example is the validation of integer controls.


% 2016.03.30. Substitute chosen special value of integer control.
    substituteSpecialInteger:(integerControl, integer SpecialChoice) procedure.

Its clauses are:


% 2016.03.30-2016.05.12. Substitute chosen special value of integer control.
substituteSpecialInteger(Control,substitute_previous) :-
    previousInteger(Control,V),
    !,
    Control:setInteger(V).
substituteSpecialInteger(Control,substitute_maximal) :-
    !,
    Control:setInteger(Control:getMaximum()).
substituteSpecialInteger(Control,substitute_minimal) :-
    Control:setInteger(Control:getMinimum()),
    !.
substituteSpecialInteger(Control,_) :-
    defaultInteger(Control,V),
    !,
    Control:setInteger(V).
substituteSpecialInteger(_,_).

2) You can add a timeout property to the extended ask dialog:


% 2014 Ferenc Nagy Budapest, Hungary
% 2016.05.12.-2014.10.21. Extended common dialogs
class extendedCommonDialogs
    open core

constants
   % Maximal timeout.
   max_timeout = 86400.  % Count of seconds in a day.

predicates
    % Ask with more than 3 answers.
    ask : (string Title, string Prompt, string* ButtonTitlesList, positive Default) -> integer Answer.

properties
   % 2016.05.12.
   timeout: positive . % Timeout of dialog in seconds.
   default: positive.
    % 2016.04.24.
    % Height factor.
   height_factor : real.
   % Fixed additon to text height.
   height_plus : positive.
  % Vertical gap between buttons.
   vertical_gap : positive.

end class extendedCommonDialogs

The facts related to timeout in the *.pro file are:


class facts
    timeout: positive := max_timeout. % Timeout of dialog in seconds.
    myTimer : timerId := erroneous.  % &#1080;&#1076;&#1077;&#1085;&#1090;&#1080;&#1092;&#1080;&#1082;&#1072;&#1090;&#1086;&#1088; &#1090;&#1072;&#1081;&#1084;&#1077;&#1088;&#1072;

The event handlers capable to give back the default value in case of timeout are below.


class predicates
    dlg_ask_eh : ehandler.
clauses
    dlg_ask_eh(Win,e_Create(_))=gui_api::rNull :-
        H=winGetCtlHandle(Win,convert(ctlId,default)),
        % Added on 2016.05.12.
        if timeout<max_timeout then
            myTimer := timerSet(Win,1000*timeout)
        end if,
        winSetFocus(H).

    dlg_ask_eh(Win,e_Control(I,_,_,_CtrlInfo)) = gui_api::rNull:-
        ask_result := I,
        vpi::winDestroy(Win).

% 2016.05.12. Give back the default answer in case of timeout.
   dlg_ask_eh(Win,e_Timer(myTimer))=gui_api::rNull :-
        ask_result := default,
        vpi::winDestroy(Win).

The timeout can be preset in the constructor of the main form (A) or just before the call of the extended ask dialog (B).
A)


clauses
    new(Parent) :-
        formWindow::new(Parent),
        russian::setRussianIntegerMessages(),
        russian::setRussianRealMessages(),
        myDialogTricks::substitute:=russian::substitute,
        myDialogTricks::value_choice_list:=russian::value_choice_list,
        extendedCommonDialogs::height_factor :=1.25,
        extendedCommonDialogs::height_plus:= 5,
        extendedCommonDialogs::vertical_gap:=10,
        extendedCommonDialogs::timeout:=120, % <=== 2016.05.12.
        generatedInitialize().

B)


predicates
    onIntersectValidate:() -> control::validateResult.
clauses
    onIntersectValidate() = control::contentsInvalid(birth_lbx,death_lbx,Msg) :-
        list::intersection(birth_lbx:getSelectedIndices(),death_lbx:getSelectedIndices())=Intersection,
        Intersection<>[],
        Title=string::format("% %",mystring::deleteAmpersand(fate_gb),"&#1085;&#1077;&#1076;&#1086;&#1087;&#1091;&#1089;&#1090;&#1080;&#1084;&#1099;"),
        F="&#1044;&#1083;&#1103; &#1082;&#1088;&#1080;&#1090;&#1077;&#1088;&#1080;&#1081; &#1088;&#1086;&#1078;&#1076;&#1077;&#1085;&#1080;&#1103; &#1080; &#1076;&#1083;&#1103; &#1082;&#1088;&#1080;&#1090;&#1077;&#1088;&#1080;&#1081; &#1089;&#1084;&#1077;&#1088;&#1090;&#1080;\n"
            "&#1085;&#1077;&#1083;&#1100;&#1079;&#1103; &#1074;&#1099;&#1088;&#1072;&#1090;&#1100; &#1088;&#1072;&#1074;&#1085;&#1099;&#1077; &#1095;&#1080;&#1089;&#1083;&#1072; &#1089;&#1086;&#1089;&#1077;&#1076;&#1077;&#1081; %.\n&#1042;&#1099;&#1090;&#1088;&#1080; &#1089;&#1077;&#1095;&#1077;&#1085;&#1080;&#1077; &#1089; ...",
        Msg=string::format(F,toString(Intersection)),
        % 2016.05.12. You can insert the local timeout here i seconds (not in milliseconds).
        % extendedCommonDialogs::timeout:=240, % <=== 2016.05.12.
        Del=extendedCommonDialogs::ask(Title,Msg,
            ["&#1050;&#1088;&#1080;&#1090;&#1077;&#1088;&#1080;&#1080; &&#1088;&#1086;&#1078;&#1076;&#1077;&#1085;&#1080;&#1103;", "&#1050;&#1088;&#1080;&#1090;&#1077;&#1088;&#1080;&#1080; &&#1089;&#1084;&#1077;&#1088;&#1090;&#1080;","&&#1054;&#1073;&#1077;&#1080;&#1093; &#1089;&#1087;&#1080;&#1089;&#1082;&#1086;&#1074;"],2),
        unselectIntersection(Del,InterSection,birth_lbx,death_lbx),
       !.
onIntersectValidate() = control::contentsOk.


_________________
TIA, Regards,
Frank Nagy
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 12 May 2016 17:40    Post subject: Reply with quote

Frank,

Those are useful extensions, thanks for posting the code. Smile

When developing in VIP 5.2 I created a timed dialog to inform user of successful completion of some action. The dialog would appear for a certain period of time (seconds) and the lazy users wouldn't have to click [OK]. Too many applications require you to click unnecessarily for routine operation notifications. The predicate signature was something like this:

adviseUser : ( window ParentWin, string Title, string Msg, positive DisplayTimeSeconds ).

If I recreate that in 7.5, I'll probably add a boolean parameter to optionally write the Title and Message to the application log file.

I'll take some time to study your code.
Thanks again,
Harrison
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    discuss.visual-prolog.com Forum Index -> Visual Prolog Tips & Samples All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum