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

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?

Related

How to get cursor position of McCLIM

I'm trying to add Input Method supportto McCLIM so that it can input CJK in McCLIM, using input method client like fcitx.
To draw fcitx better, I want to get the cursor position of text editing area when it changed.
looks like this:
I found something called cursor-position/stream-cursor-position, but I don't know how to get the cursor/stream currently focus on. I have tried *standard-output*, but it failed.
How could I do this?
I know you're not using libx11, but I'd like just show you how libX11 do this.
Basically this is done by XIM_SET_IC_VALUES in the protocol. The values the spot location within a nested value of preedit attributes.
The spot is simply a X point (x, y). Despite of that, the point is a relative coordinates to the focus window. The focus window is also a part of ic vlaues, with property name XNFocusWindow.
If you don't set focus window, the client window that passed through XCreateIC will be used as the focus window.
XVaNestedList preedit_attr;
preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &nspot, NULL);
XSetICValues(ic, XNPreeditAttributes, preedit_attr, NULL);
XFree(preedit_attr);

LibreOffice macro showing simple TextBox shape

I cannot figure out (or find an example) how to perform the following simple thing in the LibreOffice Calc 6.2:
I have a drawing shape (e.g. a simple rectangle) in a sheet (call it ShapeA) and a textbox shape in another sheet (call it TextboxB). I want to do the following: when I click on the ShapeA, the TextboxB must appear on the screen (without changing the current sheet, maybe in a dialog box) and then be closed with a mouse click.
I guess the macro associated with ShapeA could look something like this:
Sub Main
oDrawPage = ThisComponent.getDrawPage()
oTb = oDrawPage.getByName("TextBoxB")
oTb.show()
End Sub
Could someone advise what I should put into this macro to accomplish the described task?
UPDATE: What I want to accomplish ( in reply to Jim K.).
I have a very cluttered diagram with many shapes. Each shape has some textual information associated with it. There is not enough space on each shape or around it to contain this info. So there is must be a way to display this info about each shape. Also this information should be displayed in a preformatted way (it contains code and other structured info).
My plan is to create a textbox with the relevant information for each diagram shape, place these textboxes in other sheet and have a possibility, when viewing diagram, to click on any shape and view the associated info in the poped up textbox without leaving the diagram, and then close the textbox with a simple action (e.g. by clicking on it).
Does this task sound feasible to be realized with the LO's shapes and macros?
How about this: Put everything on the same sheet but keep the text boxes hidden until needed.
Use the following code adapted from https://ask.libreoffice.org/en/question/93050/how-can-i-hideshow-a-shape-of-my-spreadsheet-using-a-macro/.
Sub ShapeClickedA
ShowHideShape("TextBoxA")
End Sub
Sub ShapeClickedB
ShowHideShape("TextBoxB")
End Sub
Sub ShowHideShape(shapeName As String)
oDrawPage = ThisComponent.getSheets().getByName("Sheet1").getDrawPage()
For iShape = 0 To oDrawPage.Count - 1
oShape = oDrawPage.getByIndex(iShape)
If oShape.Name = shapeName Then
If oShape.Visible Then
oShape.Visible = 0 'Not Visible
Else
oShape.Visible = 1 'Visible
End If
End If
Next iShape
End Sub
If you haven't yet, set the names of the text boxes by right-clicking and choosing Name... Then right click on both ShapeA and TextBoxA and assign the macro ShapeClickedA. Do likewise for other pairs of shapes. The result works like this:
Before anything is clicked.
Click on ShapeA. (To close it again, click on either ShapeA or TextBoxA). ShapeB functions similarly.
It's also possible to display both at the same time.

Coordinating overobj and toolbar buttons to set pointer in 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.

matlab KeyPressFcn for holding a key

I would like to allow the user to zoom only while the control key is held (depressed). I have implemented this as follows within a WindowKeyPressFcn callback function:
function keypress_callback(obj, evd, hZoom)
switch evd.Key
case 'control'
set(hZoom,'Enable','on');
end
%disp(evd); % used for debugging purposes
This function accepts a zoom object handle (hZoom) that is passed from the main program at the moment the callback function is activated (set(hFigure,'WindowKeyPressFcn',{#keypress_callback,hZoom});). I have written a similar WindowKeyReleaseFcn (set via set(hFigure,'WindowKeyReleaseFcn',{#keyrelease_callback,hZoom});) to disable zooming when control is released.
function keyrelease_callback(obj, evd, hZoom)
switch evd.Key
case 'control'
set(hZoom,'Enable','off');
end
%disp(evd); % used for debugging purposes
The goal is to allow normal zooming behavior (click to zoom in by a factor; shift-click to zoom out by a factor; drag clicking to zoom in on a selected region) only while the Ctrl key is depressed. As soon as this modifier key is released, zooming ability should be disabled.
However, this behavior does not work as intended. Simply testing (by disp(evd)) whether a key is pressed reveals that any number of key presses can be made with arbitrary keys; however, if the pressed key is Ctrl, only one such press can be made, and all subsequent presses of Ctrl are ignored, while all subsequent presses of any other key cause the key to appear in the Matab command window instead of triggering the keypress_callback function. Thus, pressing Ctrl appears to somehow inactivate the keypress_callback function, perhaps because focus is shifted from the figure to the zoom object? As a corollary question, the WindowKeyReleaseFcn seems to work fine for non-modifier keys (the evd shows the correct released key), but the key in evd is empty if the released key is a non-modifier key.
I would be grateful if someone could demonstrate the correct implementation of the control-dependent zoom behavior as envisaged.
The more modern way to do things seems to be:
gca
zoom on
z = zoom(gcf);
set(z, 'ButtonDownFilter', #ZoomGate)
where ZoomGate.m contains something like:
function inhibitZoom = ZoomGate(varargin)
if ismember('control', get(gcbo,'currentModifier'))
inhibitZoom = 0;
else
inhibitZoom = 1;
end
EDIT in response to questioner's comments:
My first suggestion was to use a WindowButtonDownFcn callback which then calls zoom itself if it detects the control modifier. This is fine provided you have control over the zoom implementation. Looking back at my code (I did something like this anything up to 15 years ago) I find that it used to be simple — zoom was an m-file and had an obvious way of calling it: zoom down meant "the button has just been pressed". Then, in that way that they do, MathWorks moved the goal posts and changed zoom. It looks like my response at the time was to re-implement my own zoom in the older, simpler style. Doesn't help you, unless you actually want that code (let me know).

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.