Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Disabling menu entries in deployed docked figures

November 14, 2012 14 Comments

Last week I presented an article explaining how to solve an issue with deployed (compiled) Matlab applications. Today I’d like to welcome guest blogger Alexander Mering, who will explain how to disable standard Matlab menu items in deployed docked Matlab figures. Alexander has been an avid follower of this blog, and from his CSSM posts we can tell that he’s been heavily using advanced GUI features presented in this blog. His article today nicely shows how we can use different building-blocks presented in different articles in this blog, to achieve something new and useful.
As Yair pointed out in many occasions, the power of Matlab could be greatly enhanced using the underlying Java mechanism. To me, while developing a larger standalone tool for technical calculations, these hints are worth a mint (as I guess for many of you).
One of these very useful hints is the ability to dock figure windows in standalone applications. This perfectly fits to my understanding of a “clean desktop”, i.e., having as less as possible separate windows. Since in many calculations dozens of figures are generated, the desktop gets up crowded very fast – if these are not grouped. So docking is essential (at least for me). Unfortunately there seems to be a serious problem with the resulting menu entries (at least in R2011b on Win XP), leading to a crash of the standalone application. Based on the posts by Yair, I will sketch a possible route to avoid this issue.

The symptom

In the compiled application, docking could be accomplished by accessing the figure frame’s underlying Java level:

% get java frame for sophisticated modifications
jframe = get(handle(figure_handle), 'JavaFrame');
% allow docking
jframe.fHG1Client.setClientDockable(true)

% get java frame for sophisticated modifications jframe = get(handle(figure_handle), 'JavaFrame'); % allow docking jframe.fHG1Client.setClientDockable(true)

Using this modification, the user is now allowed to dock and undock the figures manually. For initial docking of the figure,

javaFrame.fHG1Client.setClientWindowStyle(true,false)

javaFrame.fHG1Client.setClientWindowStyle(true,false)

could be used during figure creation. Unfortunately, there are menu entries in the Figures container which are either unwanted (since not usable) or even directly crash the standalone applications:

Useless Debug menu items in deployed applications
Useless Debug menu items in deployed applications

Menu items crashing deployed applications
Menu items crashing deployed applications

Since crashing menu entries will be found and used by end-users (though these are somehow hidden), these prohibit the usage of the docking feature as long as these could be invoked. So how can we disable / remove these menu items?

The unsuccessful solution

Unfortunately, the straight forward solution of getting the handle to the Figures containers’ menu bar and remove the unwanted items does not work. The reason for this is the (to me unexpected behavior) that the menu bar seems to be rebuilt whenever a figure is docked/undocked.
This is actually the same behavior that automatically rebuilds the Editor’s menu bar whenever an editor file is added/removed. The Editor container is basically the same docking container as the Figures container, as shown by Yair’s setFigDockGroup utility:

Docking a figure in the Editor container (group)
Docking a figure in the Editor container (group)

Therefore, removing unwanted menu items only helps until the next figure docking/undocking. To make it even worse: also pressing any of the buttons within the document bar (if having more than one figure) somehow rebuilds the entire menu structure, reverting our changes. So the solution becomes a bit more complex.

The working solution

For the working solution, many pieces presented by Yair should be put together. The first piece results from the question how to detect a dock/undock event. Since no such callback is defined, we need to use a property listener as Yair showed in his post about the continuous slider callback:

% listen to the WindowStyle property to detect docking / undocking events
hProp = findprop(handle(figure_handle),'WindowStyle');  % a schema.prop object
% if the event occurs, invoke the callback
hlistener = handle.listener(handle(figure_handle), hProp, 'PropertyPostSet',{@(source, event) Callback_DockingFcn});
% attach listener to the GUI since it needs to be known (as long as the figure exists)
setappdata(figure_handle, 'Handle_Listener', hlistener);

% listen to the WindowStyle property to detect docking / undocking events hProp = findprop(handle(figure_handle),'WindowStyle'); % a schema.prop object % if the event occurs, invoke the callback hlistener = handle.listener(handle(figure_handle), hProp, 'PropertyPostSet',{@(source, event) Callback_DockingFcn}); % attach listener to the GUI since it needs to be known (as long as the figure exists) setappdata(figure_handle, 'Handle_Listener', hlistener);

Now, whenever the figure’s WindowStyle property (which controls the docking state) is changed, our docking callback is invoked.
The next piece of the puzzle takes care of the menu rebuild whenever any document bar button is pressed. To overcome this behavior, the idea is to define the MousePressed callback of theses buttons to (again) invoke the docking callback. This is necessary for two reasons: First, pressing the button (i.e., changing the current figure) rebuilds the menu, overwriting our changed menu entries. Secondly, all other buttons are also somehow rebuilt and the callbacks are removed if a new figure is docked.
The handles to the document bar buttons could be found using Yair’s findjobj utility. We have already seen that the Editor container is analogous to the Figures docking container. So let’s use the method described by Yair for accessing the Editor container, to access the Figures container:

figures_container = javaObjectEDT(matlab_instance.getGroupContainer('Figures'));
figures_frame = javaObjectEDT(figures_container.getTopLevelAncestor);

figures_container = javaObjectEDT(matlab_instance.getGroupContainer('Figures')); figures_frame = javaObjectEDT(figures_container.getTopLevelAncestor);

Once we get the Java Frame for the Figures container, the buttons could be found by digging through its children. This finally allows to set the callback using

DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0));
ContentPanel = javaObjectEDT(DTDocumentBar.getComponent(0).getComponent(0).getViewport.getView);
if ~isempty(ContentPanel.getComponents) % less than two documents are open and no DTDocumentbar exists
    drawnow; pause(0.05)
    GroupPanel = javaObjectEDT(ContentPanel.getComponent(0));
    GroupPanel_Elements = javaObjectEDT(GroupPanel.getComponents);
    % change the MousePressed Callback for each of the buttons to invoke the function which disables the menu
    for n = 1 : GroupPanel.getComponentCount
        thisElement = GroupPanel_Elements(n);
        if isequal(char(thisElement.getClass.toString), 'class com.mathworks.widgets.desk.DTDocumentBar$DocumentButton')
            set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Cbrake_Callback_Diagrams_DockingFcn})
        end
    end
    drawnow; pause(0.05)
end

DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0)); ContentPanel = javaObjectEDT(DTDocumentBar.getComponent(0).getComponent(0).getViewport.getView); if ~isempty(ContentPanel.getComponents) % less than two documents are open and no DTDocumentbar exists drawnow; pause(0.05) GroupPanel = javaObjectEDT(ContentPanel.getComponent(0)); GroupPanel_Elements = javaObjectEDT(GroupPanel.getComponents); % change the MousePressed Callback for each of the buttons to invoke the function which disables the menu for n = 1 : GroupPanel.getComponentCount thisElement = GroupPanel_Elements(n); if isequal(char(thisElement.getClass.toString), 'class com.mathworks.widgets.desk.DTDocumentBar$DocumentButton') set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Cbrake_Callback_Diagrams_DockingFcn}) end end drawnow; pause(0.05) end

where the loop runs through the current buttons in the document bar.
As the last step of our procedure, we finally remove (or disable) the menu entries which are unwanted. This is achieved by extracting the handle to the Figures menu by:

figures_menu = javaObjectEDT(figures_frame.getJMenuBar);

figures_menu = javaObjectEDT(figures_frame.getJMenuBar);

Running through the menu items, searching for the unwanted entries (as long as they have pre-defined menu-item names) at the end sets us into the position to take care of the menu items:

% run through top-level menu items
for n = 1 : figures_menu.getMenuCount
    % completely deactivate Debugging options
    if isequal(char(figures_menu.getMenu(n-1).getName), 'DesktopDebugMenu')
        DesktopDebugMenuPos = n - 1;
    end
    % Remove some items from the Desktop menu
    if isequal(char(figures_menu.getMenu(n-1).getName), 'DesktopMenu')
        desktop_menu = javaObjectEDT(figures_menu.getMenu(n-1));
        DeletePos = [];
        for m = 1: desktop_menu.getMenuComponentCount
            if ismember({char(desktop_menu.getMenuComponent(m-1).getName)}, ...
                        {'ToggleFigure PaletteCheckBoxMenuItem', 'TogglePlot BrowserCheckBoxMenuItem', 'ToggleProperty EditorCheckBoxMenuItem'})
                DeletePos(end+1) = m - 1;
            end
        end
        for m = length(DeletePos) : -1 : 1
            desktop_menu.remove(DeletePos(m))
        end
    end
end
% finally remove the "Debug" menu
if ~isempty(DesktopDebugMenuPos)
    figures_menu.remove(DesktopDebugMenuPos)
end

% run through top-level menu items for n = 1 : figures_menu.getMenuCount % completely deactivate Debugging options if isequal(char(figures_menu.getMenu(n-1).getName), 'DesktopDebugMenu') DesktopDebugMenuPos = n - 1; end % Remove some items from the Desktop menu if isequal(char(figures_menu.getMenu(n-1).getName), 'DesktopMenu') desktop_menu = javaObjectEDT(figures_menu.getMenu(n-1)); DeletePos = []; for m = 1: desktop_menu.getMenuComponentCount if ismember({char(desktop_menu.getMenuComponent(m-1).getName)}, ... {'ToggleFigure PaletteCheckBoxMenuItem', 'TogglePlot BrowserCheckBoxMenuItem', 'ToggleProperty EditorCheckBoxMenuItem'}) DeletePos(end+1) = m - 1; end end for m = length(DeletePos) : -1 : 1 desktop_menu.remove(DeletePos(m)) end end end % finally remove the "Debug" menu if ~isempty(DesktopDebugMenuPos) figures_menu.remove(DesktopDebugMenuPos) end

Since this callback is invoked whenever a figure is docked/undocked, or the currently shown figure is changed (by pressing the document bar button), all unwanted menu items within the Figures menu could be removed.
As a result, the new Figures container menu looks like:

Deployed menu without unwanted items
Deployed menu without unwanted items

Remarks

I must admit that above solution is still imperfect. For instance, sometimes there is a larger delay between the docking (or button press event) and the removing of the menu item. Nevertheless, this solution allows me to distribute my standalone with docked figures without having menu items directly leading to a fatal error.
Obviously, the solution has some positive side effects:

  • As could be seen from the screen shot, the Matlab desktop becomes available also within your compiled applications. This might be wanted. If not, it could be removed the same way as the other menu items. One drawback of making the desktop available should be mentioned: In my tests, the standalone Matlab desktop shows the whole list of recent files I have in the Matlab editor at compile time. This is somehow ugly but not that problematic.
  • Additional menu items could be added, giving more possibilities for modifications.

I have uploaded a first version of the docking and creation functions, together with a small test project, to the Matlab file Exchange. Readers are welcome to download the code and send me improvement suggestions. Or you could simply leave a comment below.

Related posts:

  1. Docking figures in compiled applications – Figures in compiled applications cannot officially be docked since R2008a, but this can be done using a simple undocumented trick....
  2. Using pure Java GUI in deployed Matlab apps – Using pure-Java GUI in deployed Matlab apps requires a special yet simple adaptation. ...
  3. Matlab toolstrip – part 9 (popup figures) – Custom popup figures can be attached to Matlab GUI toolstrip controls. ...
  4. JGraph in Matlab figures – JGraph is a powerful open-source Java library that can easily be integrated in Matlab figures. ...
  5. Removing user preferences from deployed apps – An unsupported MathWorks Technical Solution explains how to remove private information from deployed (compiled) matlab applications. ...
  6. Splash window for deployed applications – Deployed (compiled) Matlab applications take a long time to load. I present a splash window that loads immadiately, solving this problem. ...
Alexander Mering Callbacks Compiler Desktop Docking FindJObj Java JavaFrame Listener Menubar Undocumented feature
Print Print
« Previous
Next »
14 Responses
  1. Alexander November 15, 2012 at 03:14 Reply

    As Aurelien just pointed out on the FEX, I do have a wrong definition of the MousePressedCallback. I overlooked it when extracting it from my project. So,

     set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Cbrake_Callback_Diagrams_DockingFcn})

    set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Cbrake_Callback_Diagrams_DockingFcn})

    should be changed to

     set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Callback_DockingFcn})

    set(handle(thisElement, 'CallbackProperties'), 'MousePressedCallback', {@(source, event) Callback_DockingFcn})

    I already made an update to the FEX.

  2. Raja Amirthalingam February 15, 2014 at 14:18 Reply

    Hi,

    In the Callback_DockingFcn of yours, I am getting error in the line.

    DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0));

    DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0));

    Can you tell me whats wrong?

    Thanks.

    Raja

    • Yair Altman February 15, 2014 at 14:26 Reply

      @Raja – as you can see from this complex line, it highly depends on the exact container hierarchy and so it is not surprising that it may be slightly different on a different platform and/or Matlab release. You will need to carefully look at the various elements to check how to modify it for your particular needs. A good way to see this is to run the following code in your Matlab command prompt after the figure is displayed:

      figures_frame.getRootPane.getLayeredPane.list

      figures_frame.getRootPane.getLayeredPane.list

      You will see the hierarchy of the sub-containers and you can easily navigate them via .getComponent(index). Just remember that index 0 means the first child, 1 means the second etc.

      If you need professional help, consider employing my consulting services. Use the email link at the top of this page.

      • Raja Amirthalingam February 15, 2014 at 15:18

        Hi Yair,

        It is taking a long time to execute this command, any idea?

        Thanks.

        Raja

      • Raja March 19, 2014 at 16:22

        Hi Yair,

        I figured it out using your suggestions.

        I am still fixing some issues, but I get the general Idea.

        Thanks!
        Raja

      • Raja March 19, 2014 at 16:26

        Hi Yair,

        There is one little issue. When docking and undocking, the menu comes back. Is it possible to add a listener to the ComponentCount Property of the Menu Bar?

        Thanks.
        Raja

      • Yair Altman March 20, 2014 at 00:49

        @Raja – try using ComponentAddedCallback or ComponentRemovedCallback. See here.

  3. Thierry Dalon March 27, 2014 at 01:10 Reply

    Instead of

    DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0));

    DTDocumentBar = javaObjectEDT(figures_frame.getRootPane.getLayeredPane.getComponent(1).getComponent(1).getComponent(0).getComponent(0).getComponent(1).getComponent(0));

    one could use the great findjobj:

    hDocumentButtons=findjobj(container,'class','DTDocumentBar$DocumentButton');

    hDocumentButtons=findjobj(container,'class','DTDocumentBar$DocumentButton');

    or for Matlab >=R2012a:

    hTabs=findjobj(container,'class','DTDocumentTabs$Tab');

    hTabs=findjobj(container,'class','DTDocumentTabs$Tab');

    You can also view the elements structure by using findjobj without outputs.

  4. haya January 29, 2015 at 07:47 Reply

    hi
    I’m having a similar yet different issue.
    on my deployed application the user can generate plots(figures).
    The figures which are generated on the compiled application has only ‘File’ in the MenueBar and does not have all the options on the ToolBar. The one which is mostly required is the ‘arrow’, with which the user can choose part of the figure such as the legend window, title, axes and edit them and their properties.
    Obviously, when running on matlab the figure has all its tools.
    I’m looking for a way to display and enable menu/tool entries in deployed figure

    • Yair Altman January 29, 2015 at 08:09 Reply

      @Haya – the interactive plot editing functionality is not enabled in deployed application. You will need to do this programmatically in your code if you need it in the deployed app.

      • haya February 1, 2015 at 02:19

        @Yair -first, thank you for your answer
        This is precisely what i’m asking, I can I do this programmatically?
        I compiled my code with MATLAB and I it as an .exe process from my .Net application.
        The user can generate figures from the MATLAB .exe which is hosted in my .Net app, but once the figure opens it is missing the ‘Exploration.Pan’ option in the tools bar and also all option in the menu bar but the ‘File’
        Any idea how to do this programmatically?

      • Yair Altman February 1, 2015 at 10:44

        @Haya – you did not understand. The plot-editing functionality does not exist in deployed apps. You cannot simply restore the menu item because the functionality itself does not exist. You will need to program the entire functionality yourself if you wish (yes of course it is very difficult, quite possibly not worth all the effort).

    • haya February 1, 2015 at 23:28 Reply

      @Yair thank you again for your answer.
      I have no idea how to and from where to start this kind of code and unfortunately I must have the plot-edit functionality on my deployed app. If you have any idea how I can get started I’ll be happy to hear.
      Thank you again
      haya

  5. alsec March 24, 2018 at 22:47 Reply

    Thanks for that.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
ActiveX (6) AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
  • Nicholas (3 days 21 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Nicholas (3 days 21 hours ago): Hi Yair, Thanks for the reply. I am on Windows 10. I also forgot to mention that this all works wonderfully out of the editor. It only fails once compiled. So, yes, I have tried a...
  • Yair Altman (4 days 4 hours ago): Nicholas – yes, I used it in a compiled Windows app using R2022b (no update). You didn’t specify the Matlab code location that threw the error so I can’t help...
  • Nicholas (5 days 0 hours ago): Hi Yair, Have you attempted your displayWebPage utility (or the LightweightHelpPanel in general) within a compiled application? It appears to fail in apps derived from both R2022b...
  • João Neves (8 days 5 hours ago): I am on matlab 2021a, this still works: url = struct(struct(struct(struct(hF ig).Controller).PlatformHost). CEF).URL; but the html document is empty. Is there still a way to do...
  • Yair Altman (11 days 3 hours ago): Perhaps the class() function could assist you. Or maybe just wrap different access methods in a try-catch so that if one method fails you could access the data using another...
  • Jeroen Boschma (11 days 6 hours ago): Never mind, the new UI components have an HTML panel available. Works for me…
  • Alexandre (11 days 7 hours ago): Hi, Is there a way to test if data dictionnatry entry are signal, simulink parameters, variables … I need to access their value, but the access method depends on the data...
  • Nicholas (11 days 21 hours ago): In case anyone is looking for more info on the toolbar: I ran into some problems creating a toolbar with the lightweight panel. Previously, the Browser Panel had an addToolbar...
  • Jeroen Boschma (15 days 4 hours ago): I do not seem to get the scrollbars (horizontal…) working in Matlab 2020b. Snippets of init-code (all based on Yair’s snippets on this site) handles.text_explorer...
  • Yair Altman (43 days 6 hours ago): m_map is a mapping tool, not even created by MathWorks and not part of the basic Matlab system. I have no idea why you think that the customizations to the builtin bar function...
  • chengji chen (43 days 13 hours ago): Hi, I have tried the method, but it didn’t work. I plot figure by m_map toolbox, the xticklabel will add to the yticklabel at the left-down corner, so I want to move down...
  • Yair Altman (51 days 6 hours ago): @Alexander – this is correct. Matlab stopped including sqlite4java in R2021b (it was still included in 21a). You can download the open-source sqlite4java project from...
  • Alexander Eder (57 days 1 hour ago): Unfortunately Matlab stopped shipping sqlite4java starting with R2021(b?)
  • K (63 days 12 hours ago): Is there a way to programmatically manage which figure gets placed where? Let’s say I have 5 figures docked, and I split it into 2 x 1, I want to place 3 specific figures on the...
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top