Coordinating overobj and toolbar buttons to set pointer in Matlab - matlab

This post shows how to use the overobj function to set the pointer to change over the axes part of a gui. The problem is that this will override the pointer shape set by the zoom or pan toolbar buttons. I can test for various toolbar buttons being on like this:
if (strcmp(handles.zoom.State, 'off'))
obj_han=overobj('axes');
if ~isempty(obj_han)
set(handles.figure1,'Pointer','cross');
else
set(handles.figure1,'Pointer','arrow');
end
end
But that requires adding a new test for every tool button in the toolbar, which seems like a formula for error. How does zoom, for example, set the pointer? Is there a better way to integrate changing the pointer with the way the toolbar buttons make the change?

You could use the undocumented uimode and uimodemanager to get the current uimode and if the current uimode is empty, then none of the tools are active.
manager = uigetmodemanager(gcf);
% Only alter the pointer if the CurrentMode is empty
if isempty(manager.CurrentMode)
if ~isempty(obj_han)
set(handles.figure1, 'Pointer', 'cross')
else
set(handles.figure1, 'Pointer', 'arrow')
end
end
I would retrieve the uimodemanager outside of your callback and pass it explicitly to the callback so you don't have to retrieve it every time.

Related

In LibreOffice Calc change the size of a shape by clicking it

I have several shapes in LO Calc and I need those shapes to change their sizes when they are mouse clicked: the first click enlarges the shape, the second click restores the original size.
I'm trying to do this with a macro assigned to those shapes. My problem and my question: how to determine within a macro which shape has been clicked?
I know how to get the current selected shape:
dim doc as object
doc = ThisComponent
someVar = doc.CurrentSelection...
But a shape when clicked is not getting selected and this method is not working.
I tried to add a parameter for the event object to the macro:
sub ChangeSize( oEvent )
But this produces a message about wrong number of parameters.
Is there a way to detect the caller of a macro in LO Basic? Or maybe another way to implement size changing with a mouse click?
P.S. One can use a separate button for calling the macro and click this button after selecting the needed shape, but this way is less convenient.
EDIT: As I guessed below in the comments, the described task can be solved via the mouse and shape coordinates. The key points for the solution I found here:
How to get Document-Coordinates from a Mouse Click in an OpenOffice BASIC Macro
Instead of detecting the caller, assign a different one-line macro for each shape clicked event.
Sub ShapeClickedA
ChangeSize("ShapeA")
End Sub
Sub ShapeClickedB
ChangeSize("ShapeB")
End Sub
Related: LibreOffice macro showing simple TextBox shape
P.S. After answering, I realized you asked the linked question as well. How is this different, and is the other answer not satisfactory?

Using dat.gui slider triggers orbit controls

I'm building an origami simulator, I want to be able to 'fold' the paper using a dat.gui slider. I want to also include orbital controls.
However, when I click on the slider and subsequently move my mouse out of the dat.gui window, the orbital controls have been triggered causing the model to jump to a different orientation.
Is there a way to prevent orbital controls from being triggered when I click in the dat.gui window?
Quoting the docs:
Constructor
OrbitControls( object : Camera, domElement : HTMLDOMElement )
object: (required) The camera to be controlled.
domElement: (optional) The HTML element used for event listeners. By default this is the whole document, however if you only want to the controls to work over a specific element (e.g. the canvas) you can specify that here.
In other words, to restrict the OrbitControls so that they don't enable when you click on the GUI, you must supply a reference to the canvas (renderer.domElement) or container (a div that contains the canvas) as second argument to the constructor. Happy coding! (And folding!)
My solution to your question is to: have dat.GUI "listen" to the values controlled by OrbitControls (the camera), so that the values are in sync between the two different "controllers" (OrderbitControls and dat.GUI), like so:
let gui = new dat.GUI();
let folder1 = gui.addFolder("Camera Position");
folder1.add(camera.position, "x", -100, 100).listen();
folder1.add(camera.position, "y", -100, 100).listen();
folder1.add(camera.position, "z", -100, 100).listen();
The listen() function on a tracked variable in dat.GUI will keep the values in sync, and relieve the "jumpiness" you are experiencing.
Reference to dat.GUI Controller functions documentation:
dat.gui
OrbitControls has an "enabled" property (in fact, I believe all of the controls have an "enabled" property - might want to check though). So if you have
orbitControls = new THREE.OrbitControls(...);
...
// in your dat.GUI block of code (or wherever you want to disable orbitControls)
orbitControls.enabled = false;
// this should disable orbitControls, and when you want to use orbitControls again, just do
orbitControls.enabled = true;

Get state of MATLAB GUI radiobuttons?

I have two radio buttons in my interface. I also have some pushbuttons. When ever I click a pushbutton I want it to call a function according to the selected radio button.
I tried adding the function given below
function rotation_SelectionChangeFcn(hObject, eventdata, handles)]
Tag = get(hObject, 'Tag');
disp(Tag);
But nothing is coming up when I change the selection. I want to know whether there is any mistake in the way I implemented the code or is there a better way of doing this?
Whenever you use radiobuttons you might want to regroup them in button groups, then it's quite easy to play with radio buttons, and you make sure that only 1 radio button per group gets selected at any time.
For radio buttons in button groups, you want to use the following:
get(eventdata.NewValue,'Tag')
to get the tag of the new value just being selected. You can also use OldValue as well if you want.
In the callback of your pushbutton, you can query whether a radio button is activated with its 'value', i.e. 1 if it is selected.
StateRadioButton = get(handles.RadioButton1,'Value'); %assuming the tag is "RadioButton1".
The hObject property is particular for the specific callback in which it is used, otherwise you need to use the handles structure to access elements from other functions.

Check updated String parameter of an 'edit' uicontrol while it is active

I'm having a bit of trouble with Matlab's uicontrol handling. Here's the situation:
My (programmatic) GUI contains an editable text field. This field originally contains a numeric value and is supposed to always contain one. In order to ensure that, the 'String' parameter is to be repeatedly checked, converted to numeric, and re-entered into the 'String' property of the uicontrol. This is supposed to happen whenever a user enters a visible character into the text field.
Additionally, the program is supposed to notice at any point whether the current value of said text field differs from the original value, which is stored in memory. If the user closes the figure, a modal dialog opens and asks if he wants to save the change to that value or discard it. If the figure is then reopened (through the rest of the GUI), the value of the text field starts out as either the same it started out as before (if the user discarded the changes) or the changed value defined by the user.
Both of these things fail in some instances because of a strange behaviour: The uicontrol's 'String' property is only updated after the uicontrol loses focus. This is not a problem if the user wants to do other things on that GUI or knows how to handle this. I can also live with my text field only updating to a meaningful numeric value after it loses focus.
The problem is, when I close the figure via Windows' red X button in the top right corner after changing the value of the text field, but without first clicking somewhere else, the 'String' value is never updated, so the CloseRequestFcn doesn't notice the change and simply closes the window. Even pausing for a whopping 100ms and then explicitly calling the text field's Callback from within the CloseRequestFcn doesn't help, it just closes without my dialog. The reverse is also true, if I do change the value, click somewhere else, and then change it back, it will display the dialog unless I first click somewhere else again.
So the question is this: How do I ensure the uicontrol correctly updates/executes its Callback when I click the red X button provided by Windows?
And bonus question: How do I execute this Callback "on the fly" in order to correct any impossible values the user enters as soon as he does (e.g. letters other than e and i)?
Here's the isolated part of my GUI that causes the problem, copy into a file called 'guitest.m' and run in order to test what I'm talking about.
function guitest
changed = false; %// tracks changes to catch closing without saving
startval = 1; %// the starting value
handles.figure = figure('Resize','off','Toolbar','none','Menu',...
'none','Name','Change text field value','CloseRequestFcn',...
#closefig,'Visible','off'); %// not visible until fully created
handles.textfield = uicontrol('Style','edit','Units','normalized',...
'Parent',handles.figure,'String',startval,...
'Position',[.4 .6 .2 .1],'Callback',#changedValue);
handles.button = uicontrol('String','Push me','Units','normalized',...
'Parent',handles.figure,'Position',[.4 .3 .2 .2],'Callback',#dispval);
%// all done, display GUI
set(handles.figure,'Visible','on');
%// callback functions
function closefig(~,~) %// Quit program
pause(0.1);
changedValue(handles.textfield); %// update fields
if changed
disp('Do you really want to close?'); %// save dialog
else
delete(handles.figure); %// this is used as CloseRequestFcn!
end
end
function changedValue(hObject,~)
newval = uint16(str2double(get(hObject,'String')));
changed = (startval ~= newval);
end
function dispval(~,~)
disp('With buttons inside the GUI, it works properly:');
disp(get(handles.textfield,'String'));
disp(changed);
end
end
Will forcing a GUI focus change with uicontrol in your closing function provide the correct behavior? From the documentation:
uicontrol(uich) gives focus to the uicontrol specified by the handle,
uich
For the 'bonus' you're likely going to have to leverage the underlying Java. See the article on editbox data input validation from Undocumented Matlab.

uimenu buttons remain pressed and trigger also other menus by just sliding over them: pushbutton behaviour desired

I implemented various uimenus in my uitable but there appears a very annoying behaviour.
function createUItable
h = figure
...
uimenu(h,'Label','MenuButton','Callback',#someAction)
end
%---------
function someAction(~,~)
%some action
end
But after executing the callback function, the menu button remains pressed and highlighted and not even that, when I slide over the next menu button, this one is triggered also!
This behaviour was also described at Matlab Central, but without solution.
I tried the suggested:
function someAction(~,~)
%some action
set(gcbo,'Enable','off')
drawnow
set(gcbo,'Enable','on')
end
which does not change anything. set(gcbo,'Enable','off') alone would solve the sliding problem, but also disables the whole button, what I don't want.
I also tried to use the 'Checked','Visible' and 'Interuptible' property without success.
This problem must be known, any hints?
I also thought about using uicontrol instead of uimenu and use a pushbutton, but I don't get it work.
Edit: when I put my menubutton into a submenu it works perfect:
button = uimenu(h,'Label','MenuButton');
uimenu(button,'Label','MenuButton','Callback',#someAction)
Edit2:
A pushbutton works also, but how could I place it into the menubar?
I guess MATLAB implementation is this way, because setting a callback at the top-level menu is very odd.
Naturally in GUI's (not only MATLAB), when you click the top-level menu (like "File", "Edit", etc.) the standard behaviour is, that a submenu pops open rather than an immediate action being executed.
So you should only use the top-level callback to e.g. dynamically create/modify the associated submenus.
I think there are two alternatives to go:
1) If you'd like to stick to that manner (one, always-visible button-like element), then you should rather use the toolbar via a uipushtool:
hToolbar = uitoolbar(parentFigure);
uipushtool(hToolbar, 'ClickedCallback', #someAction);
This does not have the 'Label' property though, so you'll have to work with 'CData' and may be a 'TooltipString'.
2) Create a top-level menu that contains your actual action-menu:
topMenu = uimenu(parent, 'Label', 'Actions');
uimenu(topMenu, 'Label', 'MenuButton', 'callback', #someAction)
From the general point of view on GUI design, both alternatives have the benefit of being the more commonly used style, thus being more intuitive to any user.
I found an interesting work-around for this problem while keeping the callback in the TOP menu. Turns out that using the uistack function released focus from the menu item so in the top-level menu callback, I placed
uistack(hObj,'down');
uistack(hObj,'up');
drawnow;
Which does nothing to the actual ordering but releases the menu items' focus.