Subscribe for automatic updates: RSS icon RSS

Login icon Sign in for full access | Help icon Help
Advanced search

Pages: [1] 2
  Reply  |  Print  
Author Topic: ui.Interaface.loadToolBar()  (Read 23832 times)
Huy H.
Posts: 45


« on: December 13, 2018, 05:12:15 pm »

Short question:
Is it safe to CALL ui.Interface.loadToolBar(<full_path>)?  It seems to work, although the documentation says Specify the file name without the "4tb" extension and the file is searched using $FGLRESOURCEPATH.

Long explanation:
In our application, we often switch the toolbar when when switch between user navigation and input using the ui.Interface.loadToolBar().  Once in a while, we run into program bugs where after we had switch the toolbar for something, we need to switch the toolbar back to what it was before we witched it, we end up switching to the wrong toolbar. 

For instance, we have input_toolbar, nav_toolbar, nav_list_toolbar.   Let's say we are doing input...
Code
  1. BEFORE INPUT
  2.  CALL ui.Interface.loadToolBar("input_toolbar")
  3.  ...
  4.  
  5. AFTER INPUT
  6.  CALL ui.Interface.loadToolBar("nav_toolbar")
  7.  

The problem is that if the input is used in multiple places, the second call to ui.Interface.loadToolbar() might not be using the correct toolbar, it's making an assumption it shouldn't be.  We can move our code around to address this issue, but it becomes kludge.  Add to the fact that we have multiple toolbars based on front-end client and form factor, it would become a mess.

So we wrote a function to retrieve the filename of the toolbar (by inspecting the AUI tree), this ensures that the toolbar that gets reloaded is the correct one.
Code
  1. BEFORE INPUT
  2.  LET cur_tb_file = get_current_toolbar_file()
  3.  CALL ui.Interface.loadToolBar("input_toolbar")
  4.  ...
  5.  
  6. AFTER INPUT
  7.  IF LENGTH(cur_tb_file) > 0 THEN
  8.    CALL ui.Interface.loadToolBar(cur_tb_file)
  9.  END IF
  10.  

Reuben B.
Four Js
Posts: 1047


« Reply #1 on: December 13, 2018, 10:03:36 pm »

Huy,

You are taking my mind pack 15 years.  Are you aware of ui.Form.loadToolbar, or the use of TOOLBAR attribute in .per/.4fd?

When I did my initial application migration back then, we identified that the toolbar we wanted to use on a zoom/lookup/query window that was raised when user clicked on a BUTTONEDIT was different to the toolbar that was on the parent window.  As only ui.Interface.loadToolbar() was available at the time we originally had code similar to ...

Code
  1. CALL ui.Interface.loadToolbar("maintain")
  2. OPEN WINDOW ...
  3. ...
  4. INPUT
  5. ...
  6.    ON ACTION zoom
  7.       CALL ui.Interface.loadToolbar("zoom")
  8.       OPEN WINDOW ...
  9.       ...
  10.       DISPLAY ARRAY ...
  11.       ...
  12.       CLOSE WINDOW
  13.       CALL ui.Interface.loadToolbar("maintain")

... when executed this looked dumb as the toolbar on the inactive parent window would change as well, and as you discovered you have to restore the correct toolbar.

Fortunately the Genero developers of the time listened to us and in a release (it was around 1.20,1.30) they added some ui.Form methods including ui.Form.loadToolBar.  This meant the above code then became

Code
  1. OPEN WINDOW
  2. ...
  3. CALL f.loadToolbar("maintain")
  4. ...
  5. INPUT
  6. ...
  7.    ON ACTION zoom
  8.       OPEN WINDOW ...
  9.       ...
  10.       CALL f.loadToolbar("zoom")
  11.       ...
  12.       DISPLAY ARRAY
  13.       ...
  14.       CLOSE WINDOW
  15.  


Other memories from around that time in the discussion in the mailing list that was the precursor to the forum, was that a number of requests were put in to show/hide individual toolbar items.  The Genero developers at the time were insistent on was that toolbars were supposed to be static and the only change you should see is the individual buttons becoming enabled/disabled.  By using ui.Interface.loadToolbar in the middle of dialogs like you are trying does not fit in with that model.

What I found interesting was your choice of names for your toolbars.  They sound like they were functionally similar to the toolbars I had.  I can't remember our names but we had something like ...
standard - copy/cut/paste/help etc
maintain - added query/add/update/delete/first/previous/next/last items to standard
enquiry - added query/first/previous/next/last items to standard
list - added firstrow,prevpage, prevrow,nextrow,nextpage,lastrow items to standard
zoom - similar to list but included special actions associated with zoom window
both - added both maintain and list entries to standard

and the coding standard was to look at the .per and use the appropriate toolbar in a ui.Form.loadToolbar call immediately after the OPEN WINDOW.i.e if it had a TABLE then list or both was used


So rather than using ui.Interface.loadToolbar multiple times in your code, I would suggest you investigate a solution where it is only used at most once and to use ui.Form.loadToolbar / TOOLBAR to change toolbar for each window, as I believe that would be closer in keeping to the original Genero developers intentions.

Reuben






   

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Judy S.
Posts: 18


« Reply #2 on: January 07, 2019, 05:25:48 pm »

Hello,

Regarding what you wrote:

"Other memories from around that time in the discussion in the mailing list that was the precursor to the forum, was that a number of requests were put in to show/hide individual toolbar items.  The Genero developers at the time were insistent on was that toolbars were supposed to be static and the only change you should see is the individual buttons becoming enabled/disabled.  By using ui.Interface.loadToolbar in the middle of dialogs like you are trying does not fit in with that model."

I don't think I was aware of a built-in way to hide disabled/non-applicable toolbar actions. We had written our own method to hide the inactive toolbars. Can you please elaborate on another solution to accomplish this?

Thank you.
Reuben B.
Four Js
Posts: 1047


« Reply #3 on: January 08, 2019, 01:14:31 am »

Hello,

Regarding what you wrote:

"Other memories from around that time in the discussion in the mailing list that was the precursor to the forum, was that a number of requests were put in to show/hide individual toolbar items.  The Genero developers at the time were insistent on was that toolbars were supposed to be static and the only change you should see is the individual buttons becoming enabled/disabled.  By using ui.Interface.loadToolbar in the middle of dialogs like you are trying does not fit in with that model."

I don't think I was aware of a built-in way to hide disabled/non-applicable toolbar actions. We had written our own method to hide the inactive toolbars. Can you please elaborate on another solution to accomplish this?

Thank you.

Judy,

In 1.30 the developers did (reluctantly) add a way to show/hide individual toolbar items by adding the hidden attribute to them, if you look at the list of 1.30 New Features http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/fgl_whatsnew_130.html, search for "TOOLBAR and TOPMENU elements now have the hidden attribute" (or scroll down to Table 3 and look up 2 items).  Your code is probably either using DOM Tree techniques to find the appropriate node, or if the toolbar belongs to a form using ui.Form.setElementHidden() to show/hide the toolbar item.

What I was pointing Huy at was what was added in 1.20 where rather than specifying toolbars, topmenu, action defaults as children of the ui.Interface.rootNode, it was possible to add them as children of ui.Form nodes.  Thus negating the need to use ui.Interface.loadToolbar in the middle of programs.  ui.Interface.loadToolbar would only really be used if you had the same toolbar throughout your application, and you would call it once around the same time you used ui.Interface.loadStyles.  With toolbars available as children of form nodes you could ensure that each form had the appropriate toolbar for that form.  There were a few ways to implement.  You could specify TOOLBAR http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_FormSpecFiles_TOOLBAR_section.html in .per/.4fd form files, or you could use ui.Form.loadToolbar http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassForm_loadToolbar.html shortly after your OPEN WINDOW WITH FORM to load the appropriate toolbar for your form or as part of a ui.Form.setDefaultInitializer http://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassForm_setDefaultInitializer.html.  If using ui.Form.setDefaultInitializer then you had to figure out a way to signal what toolbar to load for a form, typically via a value in TAG or STYLE or a naming convention for the form.

So in my implementation back then, we had a few specialised toolbars for particular modal windows such as zoom window, Main menu, printer spooler, and some more generic toolbars that had options depending if there was a table, and/or if used in a Query/Add/Update/Delete/First/Previous/Next/Last pattern and/or the form contents were editable, and then when we used OPEN WINDOW WITH FORM to load the form, our coding standard was to load one of those toolbars using ui.Form.loadToolbars on the next line, I can't recall exact reason why I did not make use of ui.Form.setDefaultInitializer but if I was doing it again I would

Reuben

 








Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Leo S.
Four Js
Posts: 126


« Reply #4 on: January 08, 2019, 03:13:19 pm »

Hi, I wonder if it would help to have an option "render the action panel as toolbar".
IMHO this would avoid all the messy code to load / unload/ hide /show toolbars/ toolbar items just to match the actions in the current dialog.
There is already a request "Need a way to order and group default action views in action panel and context menu", so if in addition to this request the rendering of the action panel would be "toolbar style" , is it something you are after ?
Leo
Leo S.
Four Js
Posts: 126


« Reply #5 on: January 08, 2019, 03:16:16 pm »

Furthermore my assumption is that folks using loadToolbar() all over the place do anyway hide the action panel , is that correct ?
Judy S.
Posts: 18


« Reply #6 on: January 08, 2019, 04:55:44 pm »

Hi Reuben and Leo,

Thank you very much for your replies.

Reuben: A long time ago we wrote a function that searches the toolbar and does perform the "hide" on the toolbar actions that are not active. But we have to add a call to that function each and every time we have any type of dialog (i.e. BEFORE MENU, BEFORE INPUT, BEFORE DISPLAY, etc.). If we don't hide the inactive toolbar icons, the toolbar ends up looking cluttered up and does not look very intelligent to show actions that the user cannot use in the application/screen/dialog, etc.

It would be nice if instead of needing to add a call to our function into every BEFORE dialog-type block, we could instead put something into the standard toolbar file to indicate that if an action is disabled, we want it hidden by default. That would be the ideal solution to this problem, and eliminate the extra step of adding a call to our function into each and every before-dialog block. I think that the ACTION panel has always had that option (don't remember exact syntax or where it is defined, but I know it has worked since the early Genero versions), while the toolbar did not have the ability to similarly set an attribute to auto-hide any toolbar action that is disabled/not-active.

Leo: I cannot speak for other developers who use Genero and set up toolbars and action panels to bind to the program's actions, however, we do use BOTH action panel and toolbars at the same time. The reason is mostly to provide another location on the window that the user can mouse-click on, and sometimes we want to not clutter up the action buttons shown on the action panel with some general-standard actions that all of our applications use, such as an About action to show program revision info.  Note that in our system, our toolbar only contains all the generic type of program actions that are common across all of our applications (example: Help, Exit Program, etc.). And we use the action panel to show the specific actions that are applicable to the specific application/form/dialog that the user is in.

So in summary, we would like to put in a request for a change to the toolbar behavior, to allow a new attribute in the toolbar file to specify *per action* that if that action is disabled/non-active action then it should be hidden, the same way we can specify this behavior for actions in the action panel.

Thanks again.
Leo S.
Four Js
Posts: 126


« Reply #7 on: January 08, 2019, 05:05:48 pm »

@Judy,
to understand you correctly:
If you call DIALOG.setActionHidden("foo",1)
and you have a toolbar item named "foo" it should be hidden, right ?

What about actions not in the current dialog ?
So you have an action "bar" , but its not in the current dialog.
Currently it is visible , but disabled. Should there be a new attribute to hide this item if it is not contained in the current dialog ?
Leo
Sebastien F.
Four Js
Posts: 509


« Reply #8 on: January 08, 2019, 05:23:39 pm »

@Leo:

If you call DIALOG.setActionHidden("foo",1)
and you have a toolbar item named "foo" it should be hidden, right ?

The purpose of these methods is to apply only to the default action views:

https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassDialog_setActionHidden.html
https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassDialog_setActionImage.html
https://4js.com/online_documentation/fjs-fgl-manual-html/#fgl-topics/c_fgl_ClassDialog_setActionText.html

Take care to not suggest changes that would affect other customer applications.

Seb
Reuben B.
Four Js
Posts: 1047


« Reply #9 on: January 09, 2019, 12:35:06 am »

Furthermore my assumption is that folks using loadToolbar() all over the place do anyway hide the action panel , is that correct ?
Leo,
For me incorrect, we used the toolbar for common actions Editcopy, Editcut, Editpaste, Query, Insert, Update, Delete, First, Previous, Next, Last, Help, Drilldown, Zoom etc

One off actions did not warrant the investment in a image for a toolbar entry  and so were left to appear in the action panel.  We also used actionPanelPosition=bottom to visually separate.  That worked very well.

Similarly for mobile applications such as Pool Doctors demo, actionPanel and toolBar is used simultaneously.  Only in this case, toolBar is positioned along the bottom in easy reach of thumb with buttons in a consistent order, and seperate from the actionPanel at the top.

I think you are closer with this comment
Quote
Hi, I wonder if it would help to have an option "render the action panel as toolbar".
IMHO this would avoid all the messy code to load / unload/ hide /show toolbars/ toolbar items just to match the actions in the current dialog.
There is already a request "Need a way to order and group default action views in action panel and context menu", so if in addition to this request the rendering of the action panel would be "toolbar style" , is it something you are after ?
you can go close with existing styles
Code
  1.    <StyleAttribute name="ringMenuButtonSize" value="4em" />
  2.    <StyleAttribute name="ringMenuButtonSpace" value="none" />
  3.    <StyleAttribute name="ringMenuButtonTextHidden" value="yes" />
  4.    <StyleAttribute name="ringMenuPosition" value="top" />
  5.  
(and the equivalent for actionPanel instead of ringMenu)
will give you equally sized adjacent buttons with no text.  No doubt some would like the text to appear beneath the icon.

However as you say you can't control the order of those buttons like you can with a toolbar, other than the order of the actions in the 4gl, and we still have that enhancement outstanding.  I know for my old app we had to code them so that the order of the buttons left over in the action panel matched the order of the accelerators (we wanted Ctrl-Shift-F1 to the left of Ctrl-Shift-F2 etc)

Reuben


 

Product Consultant (Asia Pacific)
Developer Relations Manager (Worldwide)
Author of https://4js.com/ask-reuben
Contributor to https://github.com/FourjsGenero
Judy S.
Posts: 18


« Reply #10 on: January 09, 2019, 06:09:28 pm »

Hello,

We follow the same principles as Reuben described: "... we used the toolbar for common actions...One off actions did not warrant the investment in a image for a toolbar entry and so were left to appear in the action panel."

Our standard toolbar file is loaded into every application. The standard toolbar contains basic, common actions. The actions that are specific to a particular application/screen/dialog are rendered via the action panel. Note that our action panel also include the same actions that are included in the standard toolbar, such as "Accept", and "Cancel", etc. simply to allow the user another option to trigger the action using the most convenient place where their mouse happens to be, or using whichever option the end-user happens to prefer at that moment.

Our toolbar is positioned at the top of the window. Our action panel is typically positioned on the right side vertically of the window, however, sometimes we might change the action panel's position to the bottom of the window, if appropriate for the particular window/form/etc.

The action panel has a DefaultView style, which allows configuring what the DEFAULT behavior for a particular action's rendering should be.
In the post where someone suggested hiding an action, that it would also hide both toolbar and action panel - yes, we use that within the 4gl dialog block in cases where the hiding is dynamic based upon changing circumstances that are driven dynamically by a user-chosen action, or particular data values.

However, my request is not to handle dynamically hiding/unhiding of a toolbar's action based upon dynamic changes related to user actions or data. It is based upon the defined actions of the current input dialog being defined or not defined in the dialog's action block.

For example, we defined a print icon in the toolbar. If an input dialog has a "on action print" statement, then we would want the print toolbar icon to be enabled, and to show. If an input dialog does NOT have any "on action print" or any other "on action" or "on key" or any other action-type statement within the input dialog that binds to the toolbar's "print" action, then we want that toolbar to both disabled and HIDDEN. Right now, Genero is automatically managing the "disabled" appearance of the toolbar icon, because it knows that there is no "action" in the input dialog that binds to the toolbar's "print" action. And if we also have a "print" action defined in our standard default actions file (i.e. "default.4ad"), Genero is automatically hiding this action in the action panel.

My request is to add a way to *configure* a toolbar action, at the specific toolbar action level, to indicate that if that particular toolbar action is not bound to any action in the current dialog, to hide it.

I.E., just like the action panel has a style attribute named "DefaultView" (I know that DefaultView is not exactly the same thing that I am asking for), I am asking for a similar type of style attribute in the toolbar that you can say how you want a non-bound action to appear: disabled/grayed-out, or hidden.

To accomplish this now, we are manually handling this by adding a call into the "BEFORE" block of each and every single dialog block (BEFORE INPUT, BEFORE MENU, BEFORE DISPLAY, etc.), to call a function we wrote named: toolbar_clean(). This function traverses the toolbar dom nodes, and for each toolbar action, searches for that action in the "Action" dom tree. If it does not find an Action node for that toolbar's action, then the function proceeds to issue a hide command on it: (call tnode.setAttribute("hidden",1)

Adding this call to tens-of-thousands of dialog blocks is tedious, and so far, we have many dialogs that were not yet modified to add in this call.

The 4gl code looks like this:
before input
. . .
call toolbar_clean()


I attached a picture of an example of a dialog that we added in our function call (toolbar_clean()) : ToolBarsCleanedUp.JPG, and another picture of an example where we have not yet added the call to toolbar_clean(): ToolBarsNotCleanedup.JPG.

As you can see from these 2 attachments, the one that has "cleaned up" toolbars looks much more professional and clutter-free than the other screen where there is a mixture of active and disabled toolbar actions, which looks messy, cluttered, and confusing to the user.

If anyone needs any further clarifications to what my request is, please feel free to let me know.

Thank you.


* ToolBarsCleanedUp.JPG (47.4 KB, 629x465 - viewed 2055 times.)

* ToolBarsNotCleanedUp.JPG (40.3 KB, 643x356 - viewed 2038 times.)
Leo S.
Four Js
Posts: 126


« Reply #11 on: January 09, 2019, 10:00:03 pm »

Hi Judy, thank you very much for the detailed explanation !
So your request is to have a kind of "auto hide" attribute for a ToolBar item.
Actions not found in the current dialog should cause the toolbar item being hidden.
If the current dialog is changed and has an action with this name it should be re shown.
Actions found in the current dialog which are disabled would still cause the the toolbar item being shown but disabled.
(Obviously the runtime would need to take care about ToolbarSeparator items too to avoid multiple separators side by side if a group got completely empty due to missing actions...)

In other words this would one enable to have a very huge toolbar for the window/form and the runtime needs to pick the suitable items...
but it would certainly remove a lot of headache to clean/restore toolbar items on each change of the current dialog.

BTW Are you using multiple dialogs ? So here the question would be too what would happen with the individual sub dialogs (and the actions inside) of the multiple dialog in case of that new toolbar item attribute set.

@Seb
I am aware that DIALOG.setActionHidden() currently only affects the action panel.
My question to Judy was to figure out if is helpful if there would be a way to make DIALOG.setActionHidden() hide toolbar actions too.
Of course no one needs to be afraid that existing code will be broken, there would be new attributes handling that case.

@Reuben
I've seen several Genero  apps not using the action panel at all (It's however indeed not something we recommend).
I am aware too that one can position the action panel on top and have a 'pseudo toolbar' action panel (And I 've seen customer apps  using this configuration  too).
But we have also seen a lot of toolbar manipulation code in user code and our goal is to reduce the amount of this manipulation code if we can find a simple set of attributes affecting the toolbar rendering better in the way customers want to affect it.
If one wants to change/modify toolbars according to the current dialog he has to write a lot of code  because of the possible nesting of dialogs (and the needed restoration in case of leaving the dialog).


Huy H.
Posts: 45


« Reply #12 on: January 09, 2019, 10:14:01 pm »

I see that my original thread totally got hijacked :-), but I like where the conversation is going.

You've got my up-vote for the ability to auto-hide toolbar buttons that are not active in the current dialog, or not supported by the current front-end client (e.g. cut/copy/paste on GBC/GMI/GMA).  It would reduce the number of different toolbars we currently have, and would reduce a lot of code managing these toolbars.
Judy S.
Posts: 18


« Reply #13 on: January 10, 2019, 05:40:22 pm »

@Huy
 "I see that my original thread totally got hijacked" - Sorry about that! I was also thinking about that when I saw how this post was taking on a life of its own - hopefully you have gotten a satisfactory response from your original post.
Judy S.
Posts: 18


« Reply #14 on: January 10, 2019, 05:42:50 pm »

@Leo
"So your request is to have a kind of "auto hide" attribute for a ToolBar item." --> YES
"Actions not found in the current dialog should cause the toolbar item being hidden." --> YES
"If the current dialog is changed and has an action with this name it should be re shown." --> YES
"Actions found in the current dialog which are disabled would still cause the the toolbar item being shown but disabled.
(Obviously the runtime would need to take care about ToolbarSeparator items too to avoid multiple separators side by side if a group got completely empty due to missing actions...) " --> YES

"In other words this would one enable to have a very huge toolbar for the window/form and the runtime needs to pick the suitable items...
but it would certainly remove a lot of headache to clean/restore toolbar items on each change of the current dialog." --> YES

"BTW Are you using multiple dialogs ? So here the question would be too what would happen with the individual sub dialogs (and the actions inside) of the multiple dialog in case of that new toolbar item attribute set." --> YES, we do; I ran an application to see what the toolbar's appearance is when you switch between each of the input statements within the multi-dialog. It is not an issue because all the inputs utilize the very same toolbar actions. However, I would think that if the actions change between inputs, then the toolbar should change accordingly; i.e. if one input has Next and Previous record actions, then the toolbar should show them when the user is actively in that input, and when they switch back to another input that does not have Next/Previous actions, those actions should be hidden.

"I am aware that DIALOG.setActionHidden() currently only affects the action panel.
My question to Judy was to figure out if is helpful if there would be a way to make DIALOG.setActionHidden() hide toolbar actions too.
Of course no one needs to be afraid that existing code will be broken, there would be new attributes handling that case." --> For our applications, we do not typically need to dynamically change the toolbar actions within the current dialog. However, please note that we sometimes want to only hide a gui button on the action panel for an action that is enabled and active, only to reduce clutter, while still showing that same action only in the toolbar. An example is our About action which shows the program's revision info, where we only may want to show it in the toolbar and keep it hidden in the action panel. So, it is ok to add a new type of setActionHidden for the toolbar, as long as we can control that it only affects just the toolbar independently from the action panel

"...But we have also seen a lot of toolbar manipulation code in user code and our goal is to reduce the amount of this manipulation code if we can find a simple set of attributes affecting the toolbar rendering better in the way customers want to affect it.
If one wants to change/modify toolbars according to the current dialog he has to write a lot of code  because of the possible nesting of dialogs (and the needed restoration in case of leaving the dialog)." --> Agree, 100%
Pages: [1] 2
  Reply  |  Print  
 
Jump to:  

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines