Can LiveCode objects be anchored to one or more sides of a form? - livecode

If so, how? ... Just for clarity, if there are 2 pixels between a form and object's edges, and I resize the form, I'd like the distance between the form and object to still be 2 pixels after resizing.
Thank you, as always.

There's a few ways to do this but the simplest and most reliable is to script it with a resizeStack handler in your card script:
on resizeStack pWidth,pHeight
put the rect of field "name" into tRect
put pWidth-2 into item 3 of tRect
set the rect of field "name" to tRect
end resizeStack

Monte's answer is dead on if what you are doing is keeping objects in a desired arrangement when resizing the stack window. But if you are wondering how to keep relative positioning while resizing or moving an object or group of objects (you said "form" so I'm assuming that's a group of objects) in a card layout, you simply have to update it in the same code that you use to resize your form or group.
constant kOffset
on resizeMyGroup
-- code for resizing group here
set the left of button "myButton" to the right of group "myForm" + kMargin
set the bottom of button "myButton" to the bottom of group "myForm"
-- etc.
end resizeMyGroup
This is the general approach to maintaining a layout in LiveCode.

Related

Can't get buttons in custom layout to return a minimal width measurement with WRAP_CONTENT

I created a custom flow layout class to lay out a series of buttons of equal height and various widths depending on what text each button displays. Each row contains as many buttons as possible, and any remaining space is distributed evenly to fill up the row. This generally works, but I can't get the buttons to be just small enough to fit their text, and as a result most of the buttons are exactly the same size.
This is how I'm creating the button and adding it to the flow:
Button button = new Button(this);
button.setMinimumWidth(0);
button.setText(eventType.get("name").asString());
button.setAllCaps(false);
button.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
button.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
eventTypeFlow.addView(button);
In the layout class' onLayout, I measure each button like this:
View child = getChildAt(childIndex);
measureChild(child, MeasureSpec.makeMeasureSpec(clientWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(clientHeight, MeasureSpec.AT_MOST));
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
But unless the text in the button is especially long, the width is always the same (264 in my case). I tried creating a linear layout XML with the button in it, setting minimum width to 0 and layout:width to wrap_content and that way the button is smaller, but when I distribute the extra space the linear layout grows, not the button.
Is there a way to get the buttons to return a smaller measurement when adding them directly to the custom layout?
Try using a LinearLayout using the layout_weight attribute. Give each button equal weight (1) and set your android:width attribute to 0dp.
Linear Layout layout_weight
More on LinearLayout's LayoutParams can be found here.
What ended up working is inflating the same linear layout XML I described in my question, then removing the button from the linear layout and adding it directly to my custom layout. Not very elegant, but it's the only thing I found that gets those buttons to be smaller.

Hiding elements in a diagram

I have a read-only diagram to visualize some data. My end users would like to "filter" the data such that only a subset of the data may be shown at one time. I realize that I can redraw the whole diagram each time I apply a filter omitting the elements that are not to be shown but I am wondering if there is a way that I can simply "hide" some existing elements dynamically and then subsequently re-show them.
To try and make crystal clear, if this were a web page instead of a diagram, I would draw the analogy of applying the CSS of display: none to elements of my choosing.
You can actually do the same with a JointJS diagram elements/links. For example:
myElement.attr('./display', 'none')
hides the whole SVG group element in which the element is rendered. Note the '.' is a special selector that points to the whole group. If you want to hide only a certain SVG subelement, you can do it similarly, e.g. for the joint.shapes.basic.Rect element, you'd do:
myRect.attr('rect/display', 'none')
This hides only the rectangle (the SVG <rect> element referenced by the tag name rect in the attrs object - that we modify via the attr() method.

Set z-index of shapes in a Kinetic.Group

How do I set z-index on the shapes that I'm adding to Kinetic.Group? My group contains rectangles and images. I want to do this:
rectangle.setZIndex(1);
image.setZIndex(2);
This gives me the following error: Uncaught TypeError: Cannot read property 'children' of undefined.
I'm using drag and drop and then grouping the objects together. I want the images to be on top of the rectangle. the moveToTop() method gives errors when I call it inside my code.
EDIT :
http://jsfiddle.net/Dcevd/ . Try this use case: drag&drop two rects, then drag the image and drop it on the first rect, then move it to the second one (when you do it inversely it works). it moves to top only on dragend.
Answer to your edit
You are calling moveToTop() on a child of the group, so it will only put the image on the op of that specific group. Once you place the second rectangle on the right stage, it gets a higher z-index then the first one your placed and will therefor be 'on top of' the first rectangle (including it's images). To solve this I've set the parent of the image (the group) to move to top on the dragstart, this fixes it for me:
cloneImg.on('dragstart', function(){
this.startX=this.x();
this.startY=this.y();
this.getParent().moveToTop();
});
See also the fiddle: http://jsfiddle.net/Dcevd/3/
PS. If you look in the KineticJS docs, you see that setZIndex is available on Kinetic images (as with all other Shapes). http://kineticjs.com/docs/Kinetic.Image.html

I don't want to change color of JButton when pressed

Color newColor = new Color(197,222,90);
JButton newButton;
newButton = new JButton(icon);
newButton.setBacgroundColor(newColor);
When it is pressed it changes color. How can I keep it from changing color? I have multiple buttons, so if there is solution in one or two rows please help me, and keep in mind that I'm beginner, writing some huge classes won't help me, because I have multiple buttons with different names to be affected with this.
EDIT: Solution in one line is:
UIManager.put("Button.select", newColor);
But it changes all button colors but I need another to have different a color.
EDIT2: After some research I figured out there isn't an easy solution (but it should be). How I see it I have 2 solutions, 1. is to break buttons to separate classes and set UIManager for them, and second is to make custom buttons. It is just too much work for button.
I've found nothing that can change that particular behavior on a normal JButton. The problem being, that whatever you write in your actionlistener for the button, will occur AFTER you've let go of the mousebutton, and not "while clicking".
There are workarounds, however.
My preferred choice is, to remove all graphics from the button, and then add your own images to the button's regular and pressed states. You could take a screenshot of your GUI, cut out the button, and set that image to be both states.
JButton myButton = new JButton();
// Sets button x, y, width, height. Make the size match the image.
myButton.setBounds(5, 30, 100, 30);
// Remove border-graphics.
myButton.setBorder(null);
// Remove default graphics from the button
myButton.setContentAreaFilled(false);
// Remove the focus-indicating dotted square when focused (optional)
myButton.setFocusPainted(false);
// Here, myImage is a simple BufferedImage object.
// You can set one like this, provided you have an "images" package,
// next to your main class (ex: com.somecompany.someprogram.images),
// that contains an image:
BufferedImage myImage = ImageIO.read(getClass().getResource("images/myImage.png"));
// Then we simply apply our image to both states for the button, and we're done.
myButton.setIcon(new ImageIcon(myImage));
myButton.setPressedIcon(new ImageIcon(myImage));
Obviously there are many ways to retain and load an image, but since that's not the issue here, I'll leave additional methods out of it.
There's no need to go through it all countless times, though. It should be pretty easy to write your own custom implementation of the JButton class, in which a custom constructor takes a single parameter, being the BufferedImage, and then the constructor sets it up accordingly (changes the icons). Then all you have to do when you create a new JButton, is to use your own class, and pass it an image:
JButton btn = new MyCustomJButton(myImage);
You could also easily get along with very few images. All you need is a HashMap which holds all the images, with a String as a key. Imagine you need 4 OK-buttons. You make a single image of a button with the text "OK" written on it. Then you put that image into the HashMap, like so:
myMap.put("OK", myImage);
Then you could do this when creating a button, over and over again if you'd like more:
JButton btn = new MyCustomJButton(myMap.get("OK"));
Alternatively:
Another way of achieving this, which is pretty elaborate, but probably considered "the right way", is to use ButtonUI, as presented in this answer to another post.
If the OP is referring to the temporary change of background colour on a button with an icon at the moment the mouse is pressed, the following statement does the trick:
button.setContentAreaFilled(false);
"If you wish to have a transparent button, such as an icon only button, for example, then you should set this to false."
This took me a long time to figure out. It seems to be a little known technique, perhaps since its name gives little clue as to its effect.
With only first lane we can still see that it is clicked. You need to combine those two:
button1.setContentAreaFilled(false);
button1.setEnabled(false);
and if you don't wanna in grey color you put another button under him.
panelname.add(button1,+5,+5); \\(first not clicable, not visible button, notice +5)
panelname.add(button2,-5,-5); \(-5,-5 means it is 5 points under panel)

How place the components the front of another one?

I want to place the components A and B over component with List. I need that would text of list will be to visible. I can not find which layout can do it.
How this behavior is in lwuit? What solutions exist?
The question is somewhat unclear, jmunoz answer is correct if you want component's A and B to reside at the bottom of the screen and the list to scroll above. However from the drawing it seems you want an "always on top" effect which you can achieve either via a glass pane (for non-interactive components) or via the LayeredLayout class.
This is actually quite simple using the following:
myForm.setLayout(new LayeredLayout());
myForm.setScrollable(false);
// will occupy the entire area of the form but should be scrollable
myForm.addComponent(componentUnderneath);
Container south = new Container(new BorderLayout());
myForm.addComponent(south);
south.addComponent(BorderLayout.SOUTH, whateverYouWantToPlaceOnTopInTheSouth);
You must do the following:
The Form must not do scroll. Use Form.setScrollable(false). Set the layout of the ´Form´ to BORDER_LAYOUT, myForm.setLayout(new BorderLayout()) . Ok in BorderLayoutyou can put the components in the Form as you want.
Put the Listcomponent in the center of the BorderLayout with myForm.addComponent(BorderLayout.CENTER, List) and the other two elements in the south of the layout using
Container southContainer = new Container();
southContainer.addComponent(A);
southContainer.addComponent(B);
myForm.addComponent(BorderLayout.SOUTH, southContainer)
With this you can get a scrollable Listand two elements always visible.

Resources