I'm using GWT PopupPanel to display a popup above a button when user clicks it.
I am setting popup's position and showing it like so:
panel.setPopupPosition(leftPos, topPos);
panel.show();
However, when I inspect the popup's top value after it shows, I see that it is positions slightly lower than what I assigned it.
The issue may be that setPopupPosition changes the values that are passed in:
// Account for the difference between absolute position and the
// body's positioning context.
left -= Document.get().getBodyOffsetLeft();
top -= Document.get().getBodyOffsetTop();
How can I make sure the GWT PopupPanel's position is exactly the values I gave it? setPopupPosition() seems to really be the only way to set the position, but it does some manipulation (which is unnecessary for my use case) to the positions I pass in.
You can use direct access to popup's DOM element to adjust PopupPanel position. But it should be done after calling show() and before making popup visible. Otherwise, you'll may see some "jump" effects.
Example:
PopupPanel popupPanel = new PopupPanel();
...
// this callback will be called after PopupPanel.show(), but before it is shown
popupPanel.setPopupPositionAndShow(new PositionCallback() {
#Override
public void setPosition(int offsetWidth, int offsetHeight) {
Style style = popupPanel.getElement().getStyle();
style.setLeft(100, Unit.PX);
style.setTop(100, Unit.PX);
}
});
Related
Here's the scenario.
A user selects an image, video, or other type of display object. It gets loaded inside a custom class known as EditableObject. The goal of EditableObject is re-sizing and re-positioning. EditableObject has 4 movieclips.
center_mc : Handles drag and drop and contains the display object.
rightside_mc : Handles re-sizing of width on mousedown
bottomside_mc : Handles re-sizing of height on mousedown
bottomright_mc : Handles scaling of object on mousedown
So far I can scale all parts of these objects. The bugs are what's causing trouble.
When I click down on the bottom or right side of the display object, the display object increases size from whichever side it's handling before I move the mouse. I get the amount to move based on the difference of the stageX and stageY positions of the mouse passed on MOUSE_DOWN and at the end of every MOUSE_MOVE. This isn't a problem, it just looks bad and currently solves the second bug..
When I handle bottomright_mc, I can only scale the object down. When trying to scale out, I have to position the mouse outside of EditableObject to get a difference greater than bottomright_mc's current position. This doesn't work because any attempts to exit the bounds of EditableObject trigger MOUSE_UP, even if I add the event listener using this.parent..
I want to be able to re-position and scale anything inside EditableObject using two sides and one corner of EditableObject when a mouse is held down and moved. Currently I can only move the object, scale the object less than its current size, and use the two sides to adjust the objects width and height but without having the mouse match the position of the side it's currently handling on initialization.
Here's an excerpt for the MOUSE_MOVE handler.
private function handleMouseMove(e:MouseEvent):void
{
switch(dragType)
{
case "right":
trace("Right triggered.");
this.width = e.stageX - this.x;
break;
case "bottom":
trace("Bottom triggered");
this.height = e.stageY - this.y;
break;
case "bottomright":
resizeMe(this, e.stageX - this.x, this.height);
break;
}
prevMouseX = e.stageX;
prevMouseY = e.stageY;
}
The full code for the class can be found here on pastebin.
Here's Editable Object in Adobe Flash CC
Here's EditableObject currently containing and handling an image inside the editor.
Based on this answer on stackoverflow provided by TOMATO in the comments, I found a great API that easily lets you handle DisplayObjects with just a few lines of code.
The one I have chosen is senocular's transform tool. A demonstration of his work can be found here. Broken down, this is how to use it.
//Constructor
var editTool:TransformTool = new TransformTool();
//Add to stage (This will not be visible until you give your TransformTool a target)
addChild(editTool);
desiredDisplayObject.addEventListener(MouseEvent.CLICK, handleMouseClick)
function handleMouseClick(e:MouseEvent):void
{
//Set the object clicked as the target for the TransformTool
editTool.target = e.target as Sprite;
//Swap the positioning in the display list so the TransformTool appears in front
editTool.parent.setChildIndex(editTool, editTool.parent.numChildren - 1);
}
You can do this a number of ways, but the basics of it is to simply add the transform tool to the stage and assign whatever display object you would like to the TransformTool.
I am building large application in Starling and one of my main problems is who should I layout first: the parent or the children?
What is the default behavior in starling and also in flash:
By default Sprite will get his size based on his children after they have been added to stage.
What if I want to layout the children based on the parent? For example: What if I want to set one of the children to be at position of 20 pixels from the bottom, like bottom menu?
In this case I should:
Add the children
Determine their sizes. If you are building your application cross platform, you need to support many screens, and many times you come to have complicate logic for calculating the scale percentage of your components, which is their size.
Determine your size and layout yourself.
now the bottom menu could be layout at 20 pixels from the bottom. Also it doesn't matter if you place this logic inside the bottom menu or it's parent.
But this not always the case, sometimes you want to layout the parent based on his children. A common example if one of the children is the parent background. In this case you should:
Add the background.
Determinate background size and layout it.
Now you can layout the parent.
But what if I got both of the cases? If one of parent children is background and the other is bottom menu? What if the bottom menu got his own background and other children that need to be layouted base on the parent?
What solution can be used so I will not get lost inside all of this, and can Gazman SDK help here?
What you need is to create layout dependencies between all the components. Each Sprite should have an event that tells us when its layouting is complete.
Now if you have some layouting logic inside the parent that cannot start until its background child is complete layouting, you should create a dependency between the background and the parent. The parent should listen to LayoutComplete event from the background and then he can layout himself, and when he complete layouting he can dispatch LayoutComplete event, and now its child bottom menu can layout himself.
You can implement it yourself or use Gazman-SDK that do exactly that. If you choose Gazman-SDK your code will look like this:
public class ParentClass extends Group
{
private var background:Background = new Background();
private var bottomMenu:BottomMenu = new BottomMenu();
override protected function initialize():void
{
// check if not already added to stage
if(!background.parent){
addChild(background);
addChild(bottomMenu);
}
// Create dependency for background. If background have not
// been initialized yet the subscription will succeed
// And this.initialize() will be called again once
// background initialize is complete
if (subscribeForInitilize(background)){
return;
}
// do layouting logic here
}
}
public class BottomMenu extends Group
{
override protected function initialize():void
{
// Create dependency for parent. If parent have not
// been initialized yet the subscription will succeed
// And this.initialize() will be called again once
// parent initialize is complete
if (subscribeForInitilize(parent as Group)){
return;
}
// do layouting logic here
}
}
I have a MovieClip called navbar and it has buttons over it. How do I connect the buttons to the MovieClip so that when the MovieClip is moved the buttons move with it? I have been able to make the navbar draggable but the buttons aren't dragged with it.
I have tried the following:
navbar.addChild(button1);
This just made the button disappear.
Your approach is correct: adding the buttons as children to the MovieClip will allow them all to be moved as one item.
The button disappearing could be any number of reasons, for instance x and y now relative to new parent (i.e. setting button y to 600 is now 600 pixels down from the navbar, not from the stage or old parent).
Try commenting out any properties you have set on the button and see if that resolves the issue, from there you can determine which property is causing the button to disappear.
So you should basically just have something like this:
var button1:Button = new Button();
navbar.addChild(button1);
If even with that minimal code doesn't result in the button displaying on the navbar, you'll need to post more code so that we can see where the problem is occurring.
you can calculate distance from Movieclip's X,Y to buttons and you can write a code like this:
var diff1:int = navbar.x - example_button1.x;
stage.addEventListener(Event.ENTER_FRAME, function(event:Event):void{
example_button1.x=navbar.x-diff1;
});
you can duplicate example_buttons and diff variables.
or you can startDrag() sametime with same event listener,
navbar.addEventListener(someEvent.some, function(event:someEvent):void{
MovieClip(root).navbar.startDrag();
MovieClip(root).example_button1.startDrag();
});
MovieClip(root) allows you to effect main stage. With this property you can effect an object from inside of navbar for example.
As you supposed, if you want the navbar and the buttons to act like a unique element you need to put buttons inside the navbar and not just over it.
The reason the button is disappearing is due to the fact that it has been put on the stage in Designer so, when you add it to navbar, you have it into two different display stacks, and that's not allowed.
You should put buttons inside the navbar in Designer, or export them for AS and then instance them dynamically, as follow:
var btn:Button1 = new Button1()
navbar.addChild(btn)
Class name Button1 is assigned in the MovieClip properties window of the Library, under Export for ActionScript.
I am building a Flex 4 application which uses a <s:Scroller> component to vertically scroll overflown content. Let me explain what happens before I ask my question:
The body of the page is loaded from a database
Once the information has loaded, the "body" of the application (in this case the list of items you see below) is constructed
Once the list is constructed, the entire encapsulating component is transitioned into view using TweenMax, like so:
myComponent.visible = true;
TweenMax.to(myComponent, 1, {
alpha : 1,
y -= 20 //Slides the component up 20px from its original location
});
Below is the result. Notice how the scrollbar is scrolled the whole way down, but you can see the tips of a few white letters that were cut off at the very bottom.
Using my custom menu, I can navigate away from the page, and come back to it, and Flex will correctly recalculate the range of the scroller so I can scroll down and see all of the desired content. This issue only happens if the initial URL that the user enters is a longer page like this one.
Any ideas on how I can force Flex to recalculate the range of the scroller?
Thank you for your time.
Ok, after many hours of researching, piecing together, and trial and error here is what I came up with.
What I was doing wrong:
When I first posted this question, the "component" that I had mentioned was already added as a child element of the <s:Scroller>, but collapsed and hidden away, like this:
<comp:MyComp alpha="0" height="0" visible="false"/>
When the data would be loaded and the component's visual appearance would be restored and transitioned into place, like this:
myComp.visible = true;
myComp.height = NaN;
myComp.invalidateSize();
myComp.height = myComp.measuredHeight;
TweenMax.to(myComp, 1, {
alpha : 1,
y -= 20 //Slides the component up 20px from its original location
});
This method of approach didn't force the <s:Scroller> to recalculate its proper size until later, sometimes not until myComp was transitioned away and another component was transitioned into place using the same method. Even then, the size of the scroller would fit the size of the previous component, not the one that is currently displaying.
Now, what I am doing correctly:
My research showed me that anytime the addElement() method is called, either directly within the <s:Scroller> itself or by any of its children, the scroller's measure() method is called, and properly re-sizes the scroller.
Instead of placing the components inside of the scroller and simply hiding them until I need them, I dynamically created them in ActionScript, set their properties, and added and removed them as needed using the addElement() and removeElement() methods respectively. Now, as old elements are transitioned away and new ones take their place, the scroller re-sizes itself correctly.
There was one final problem that I was faced with. If the very first page the user was viewing (i.e. there was no previous component that was transitioned away and destroyed) required a scroller, it wouldn't show up.
I corrected this final issue by adding an event listener that listened for when the new component had finished transitioning into place. Inside of the event handler, I explicitly set the height of the component using this code:
newComp.height = NaN;
newComp.invalidateSize();
newComp.height = newComp.measuredHeight;
Now that the component has an explicit height, the scroller now appears, even if it is the first page.
The scroller now works as expected in all cases, and does not cut off any content or disappear when it shouldn't.
I hope that it is helpful to someone.
I have a JFrame with a JTextArea: by clicking on this TextArea a JPopupMenu appears with two items "Clear" and "Save".
private void jTextArea1MousePressed(java.awt.event.MouseEvent evt) {
jPopupMenu1.setVisible(true);
}
My question is: this popup always appears at position (0,0) but I would like to show pop where mouse is clicked, inside or relative to the TextArea.
I have try setLocation(x,y) but this methods always prompt in a fixed location and it is not what I am seeking for, and it is not available a method such as setLocationRelativeTo(JTextArea());
don't use a mouseListener as trigger to show the popup, instead use the JComponent componentPopupMenu property, like
myTextArea.setComponentPopupMenu(myPopupMenu)
Doing so will show the popup on right click at the mouse position by default. It has the additional benefit of covering keyboard triggered (LAF dependend, F10 on win) popup requests as well.
If for some reason you really need to manually show the popup, the method you're looking for is
myPopup.show(myTextArea, x, y)