As stated, I want to change the default TAB behaviour within a JTextArea (so that it acts like a JTextField or similar component)
Here's the event action
private void diagInputKeyPressed(java.awt.event.KeyEvent evt) {
if(evt.KEY_PRESSED == java.awt.event.KeyEvent.VK_TAB) {
actionInput.transferFocus();
}
}
And here's the listener
diagInput.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyPressed(java.awt.event.KeyEvent evt) {
diagInputKeyPressed(evt);
}
});
I've tried evt.KEY_TYPED as well with no joy.
Any ideas?
quick edit: I've also tried requestFocus() in place of transferFocus()
According to this class:
/**
* Some components treat tabulator (TAB key) in their own way.
* Sometimes the tabulator is supposed to simply transfer the focus
* to the next focusable component.
* <br/>
* Here s how to use this class to override the "component's default"
* behavior:
* <pre>
* JTextArea area = new JTextArea(..);
* <b>TransferFocus.patch( area );</b>
* </pre>
* This should do the trick.
* This time the KeyStrokes are used.
* More elegant solution than TabTransfersFocus().
*
* #author kaimu
* #since 2006-05-14
* #version 1.0
*/
public class TransferFocus {
/**
* Patch the behaviour of a component.
* TAB transfers focus to the next focusable component,
* SHIFT+TAB transfers focus to the previous focusable component.
*
* #param c The component to be patched.
*/
public static void patch(Component c) {
Set<KeyStroke>
strokes = new HashSet<KeyStroke>(Arrays.asList(KeyStroke.getKeyStroke("pressed TAB")));
c.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, strokes);
strokes = new HashSet<KeyStroke>(Arrays.asList(KeyStroke.getKeyStroke("shift pressed TAB")));
c.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, strokes);
}
}
Note that patch() can be even shorter, according to Joshua Goldberg in the comments, since the goal is to get back default behaviors overridden by JTextArea:
component.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null);
component.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null);
This is used in question "How can I modify the behavior of the tab key in a JTextArea?"
The previous implementation involved indeed a Listener, and the a transferFocus():
/**
* Override the behaviour so that TAB key transfers the focus
* to the next focusable component.
*/
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_TAB) {
System.out.println(e.getModifiers());
if(e.getModifiers() > 0) a.transferFocusBackward();
else a.transferFocus();
e.consume();
}
}
e.consume(); might have been what you missed to make it work in your case.
Related
I'm building a user interface using JComponents.
The UI should work in this way: depending on the value set (e.g. through a JComboBox), different JComponents are displayed.
My though was to #Override the isVisible() method of each component or, alternatively, to set them visible or not through the JComboBox. Indeed, both the two methods works, in the sense that the desired components appear and disappear from JPanel when I change the JComboBox value.
The problem is that, even if a component is not visible inside the panel, it is still active and clicking on the position in which it should be (if visible), it triggers its action. E.g. I move the mouse over the position in which another JComboBox should be; the combobox is not visible, but mouse cursor turns into Cursor.HAND_CURSOR and, if I click, the popup list of combobox items appears and I'm able to select one of these items.
Here is a salmple of the code I'm using:
public class MyPanel extends JPanel{
public MyPanel(){
super(new GridBagLayout());
GridBagConstraints g = new GridBagConstraints(
0, // int gridx
-1, // int gridy
1, // int gridwidth
1, // int gridheight
1, // double weightx
1, // double weighty
GridBagConstraints.NORTHWEST, // int anchor
GridBagConstraints.NONE, // int fill
new Insets(0,0,0,0), // Insets insets
0, // int ipadx
0 // int ipady
);
String[] comboItems = {"ShowCombo1","ShowCheckbox","ShowTextField"};
JComboBox combo = new JComboBox(comboItems);
JComboBox combo1 = new JComboBox(){
#Override
public boolean isVisible(){
return combo.getSelectedIndex()==0;
}
};
JCheckBox checkBox= new JCheckBox(){
#Override
public boolean isVisible(){
return combo.getSelectedIndex()==1;
}
};
JTextField textField= new JTextField(){
#Override
public boolean isVisible(){
return combo.getSelectedIndex()==2;
}
};
add(combo,g);
g.gridy += 1;
add(combo1,g);
g.gridy += 1;
add(checkBox,g);
g.gridy += 1;
add(textField,g);
}
}
Is there a better way to manage these kind of user interfaces?
I think with your approach you are just return the flag to true based on the selection. Internally the setVisible(false) does more than just switching the flag off. It calls super.setVisible(false) which does the below.
/**
* Shows or hides this component depending on the value of parameter
* <code>b</code>.
* <p>
* This method changes layout-related information, and therefore,
* invalidates the component hierarchy.
*
* #param b if <code>true</code>, shows this component;
* otherwise, hides this component
* #see #isVisible
* #see #invalidate
* #since JDK1.1
*/
public void setVisible(boolean b) {
show(b);
}
/**
* #deprecated As of JDK version 1.1,
* replaced by <code>setVisible(boolean)</code>.
*/
#Deprecated
public void show() {
if (!visible) {
synchronized (getTreeLock()) {
visible = true;
mixOnShowing();
ComponentPeer peer = this.peer;
if (peer != null) {
peer.setVisible(true);
createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED,
this, parent,
HierarchyEvent.SHOWING_CHANGED,
Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
if (peer instanceof LightweightPeer) {
repaint();
}
updateCursorImmediately();
}
if (componentListener != null ||
(eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 ||
Toolkit.enabledOnToolkit(AWTEvent.COMPONENT_EVENT_MASK)) {
ComponentEvent e = new ComponentEvent(this,
ComponentEvent.COMPONENT_SHOWN);
Toolkit.getEventQueue().postEvent(e);
}
}
Container parent = this.parent;
if (parent != null) {
parent.invalidate();
}
}
}
Though i do not understand what they actually do :-), I feel this part of code needs to be executed.
I'm looking for a way to open a split screen editor in an Eclipse RCP application programmatically.
From an open Editor I want to open another Editor. The purpose is to compare the content of Editor1 with the content of Editor2.
What I have is the following, but this creates a split screen Editor containing the content of Editor2 twice:
MPart editorPart = editor.getSite().getService(MPart.class);
if (editorPart == null) {
return;
}
editorPart.getTags().add(IPresentationEngine.SPLIT_HORIZONTAL);
I think best would be opening Editor2 left or below the current editor, so it has its own tab and close button.
The code below splits an editor by inserting one editor into another. This is what DnD for editor tabs does in Eclipse.
/**
* Inserts the editor into the container editor.
*
* #param ratio
* the ratio
* #param where
* where to insert ({#link EModelService#LEFT_OF},
* {#link EModelService#RIGHT_OF}, {#link EModelService#ABOVE} or
* {#link EModelService#BELOW})
* #param containerEditor
* the container editor
* #param editorToInsert
* the editor to insert
*/
public void insertEditor(float ratio, int where, MPart containerEditor, MPart editorToInsert) {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
EModelService service = window.getService(EModelService.class);
MPartStack toInsert = getPartStack(editorToInsert);
MArea area = getArea(containerEditor);
MPartSashContainerElement relToElement = area.getChildren().get(0);
service.insert(toInsert, (MPartSashContainerElement) relToElement, where, ratio);
}
private MPartStack getPartStack(MPart childPart) {
MStackElement stackElement = childPart;
MPartStack newStack = BasicFactoryImpl.eINSTANCE.createPartStack();
newStack.getChildren().add(stackElement);
newStack.setSelectedElement(stackElement);
return newStack;
}
private MArea getArea(MPart containerPart) {
MUIElement targetParent = containerPart.getParent();
while (!(targetParent instanceof MArea))
targetParent = targetParent.getParent();
MArea area = (MArea) targetParent;
return area;
}
Examples of the use the insert method are below:
insertEditor(0.5f, EModelService.LEFT_OF, containerPart, childPart);
insertEditor(0.5f, EModelService.BELOW, containerPart, childPart);
In passing, code in class SplitDropAgent2 is responsible for the DnD capability of the editor tabs.
I have a class called ComponentMover that allows you to drag around any object that's registered with it. This works if you pass it bare JPanels, but it doesn't work if the JPanel has anything inside of it, and it just stays put.
This is ComponentMover:
public class ComponentMover extends MouseAdapter {
private Insets dragInsets = new Insets(0, 0, 0, 0);
private Dimension snapSize = new Dimension(1, 1);
private Insets edgeInsets = new Insets(0, 0, 0, 0);
private boolean changeCursor = true;
private boolean autoLayout = false;
private Class<?> destinationClass;
private Component destinationComponent;
private Component destination;
private Component source;
private Point pressed;
private Point location;
private Cursor originalCursor;
private boolean autoscrolls;
private boolean potentialDrag;
private boolean shouldLock = true;
/**
* Constructor for moving individual components. The components must be
* regisetered using the registerComponent() method.
*/
public ComponentMover() {
}
/**
* Constructor to specify a Class of Component that will be moved when drag
* events are generated on a registered child component. The events will be
* passed to the first ancestor of this specified class.
*
* #param destinationClass
* the Class of the ancestor component
* #param component
* the Components to be registered for forwarding drag events to
* the ancestor Component.
*/
public ComponentMover(Class<?> destinationClass, JComponent... components) {
this.destinationClass = destinationClass;
registerComponent(components);
}
/**
* Constructor to specify a parent component that will be moved when drag
* events are generated on a registered child component.
*
* #param destinationComponent
* the component drage events should be forwareded to
* #param components
* the Components to be registered for forwarding drag events to
* the parent component to be moved
*/
public ComponentMover(JComponent destinationComponent,
JComponent... components) {
this.destinationComponent = destinationComponent;
registerComponent(components);
}
public void setLock(boolean shouldLock) {
this.shouldLock = shouldLock;
}
/**
* Get the auto layout property
*
* #return the auto layout property
*/
public boolean isAutoLayout() {
return autoLayout;
}
/**
* Set the auto layout property
*
* #param autoLayout
* when true layout will be invoked on the parent container
*/
public void setAutoLayout(boolean autoLayout) {
this.autoLayout = autoLayout;
}
/**
* Get the change cursor property
*
* #return the change cursor property
*/
public boolean isChangeCursor() {
return changeCursor;
}
/**
* Set the change cursor property
*
* #param changeCursor
* when true the cursor will be changed to the Cursor.MOVE_CURSOR
* while the mouse is pressed
*/
public void setChangeCursor(boolean changeCursor) {
this.changeCursor = changeCursor;
}
/**
* Get the drag insets
*
* #return the drag insets
*/
public Insets getDragInsets() {
return dragInsets;
}
/**
* Set the drag insets. The insets specify an area where mouseDragged events
* should be ignored and therefore the component will not be moved. This
* will prevent these events from being confused with a MouseMotionListener
* that supports component resizing.
*
* #param dragInsets
*/
public void setDragInsets(Insets dragInsets) {
this.dragInsets = dragInsets;
}
/**
* Get the bounds insets
*
* #return the bounds insets
*/
public Insets getEdgeInsets() {
return edgeInsets;
}
/**
* Set the edge insets. The insets specify how close to each edge of the
* parent component that the child component can be moved. Positive values
* means the component must be contained within the parent. Negative values
* means the component can be moved outside the parent.
*
* #param edgeInsets
*/
public void setEdgeInsets(Insets edgeInsets) {
this.edgeInsets = edgeInsets;
}
/**
* Remove listeners from the specified component
*
* #param component
* the component the listeners are removed from
*/
public void deregisterComponent(JComponent... components) {
for (JComponent component : components)
component.removeMouseListener(this);
}
/**
* Add the required listeners to the specified component
*
* #param component
* the component the listeners are added to
*/
public void registerComponent(JComponent... components) {
for (JComponent component : components){
component.addMouseListener(this);
}
}
/**
* Get the snap size
*
* #return the snap size
*/
public Dimension getSnapSize() {
return snapSize;
}
/**
* Set the snap size. Forces the component to be snapped to the closest grid
* position. Snapping will occur when the mouse is dragged half way.
*/
public void setSnapSize(Dimension snapSize) {
if (snapSize.width < 1 || snapSize.height < 1)
throw new IllegalArgumentException(
"Snap sizes must be greater than 0");
this.snapSize = snapSize;
}
/**
* Setup the variables used to control the moving of the component:
*
* source - the source component of the mouse event destination - the
* component that will ultimately be moved pressed - the Point where the
* mouse was pressed in the destination component coordinates.
*/
#Override
public void mousePressed(MouseEvent e) {
source = e.getComponent();
int width = source.getSize().width - dragInsets.left - dragInsets.right;
int height = source.getSize().height - dragInsets.top
- dragInsets.bottom;
Rectangle r = new Rectangle(dragInsets.left, dragInsets.top, width,
height);
if (r.contains(e.getPoint()))
setupForDragging(e);
}
private void setupForDragging(MouseEvent e) {
source.addMouseMotionListener(this);
potentialDrag = true;
// Determine the component that will ultimately be moved
if (destinationComponent != null) {
destination = destinationComponent;
} else if (destinationClass == null) {
destination = source;
} else // forward events to destination component
{
destination = SwingUtilities.getAncestorOfClass(destinationClass,
source);
}
pressed = e.getLocationOnScreen();
location = destination.getLocation();
if (changeCursor) {
originalCursor = source.getCursor();
source.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
// Making sure autoscrolls is false will allow for smoother dragging of
// individual components
if (destination instanceof JComponent) {
JComponent jc = (JComponent) destination;
autoscrolls = jc.getAutoscrolls();
jc.setAutoscrolls(false);
}
}
/**
* Move the component to its new location. The dragged Point must be in the
* destination coordinates.
*/
#Override
public void mouseDragged(MouseEvent e) {
Point dragged = e.getLocationOnScreen();
int dragX = getDragDistance(dragged.x, pressed.x, snapSize.width);
int dragY = getDragDistance(dragged.y, pressed.y, snapSize.height);
int locationX = location.x + dragX;
int locationY = location.y + dragY;
// Mouse dragged events are not generated for every pixel the mouse
// is moved. Adjust the location to make sure we are still on a
// snap value.
if (shouldLock) {
while (locationX < edgeInsets.left)
locationX += snapSize.width;
while (locationY < edgeInsets.top)
locationY += snapSize.height;
Dimension d = getBoundingSize(destination);
while (locationX + destination.getSize().width + edgeInsets.right > d.width)
locationX -= snapSize.width;
while (locationY + destination.getSize().height + edgeInsets.bottom > d.height)
locationY -= snapSize.height;
}
// Adjustments are finished, move the component
destination.setLocation(locationX, locationY);
}
/*
* Determine how far the mouse has moved from where dragging started (Assume
* drag direction is down and right for positive drag distance)
*/
private int getDragDistance(int larger, int smaller, int snapSize) {
int halfway = snapSize / 2;
int drag = larger - smaller;
drag += (drag < 0) ? -halfway : halfway;
drag = (drag / snapSize) * snapSize;
return drag;
}
/*
* Get the bounds of the parent of the dragged component.
*/
private Dimension getBoundingSize(Component source) {
if (source instanceof Window) {
GraphicsEnvironment env = GraphicsEnvironment
.getLocalGraphicsEnvironment();
Rectangle bounds = env.getMaximumWindowBounds();
return new Dimension(bounds.width, bounds.height);
} else {
return source.getParent().getSize();
}
}
/**
* Restore the original state of the Component
*/
#Override
public void mouseReleased(MouseEvent e) {
if (!potentialDrag)
return;
source.removeMouseMotionListener(this);
potentialDrag = false;
if (changeCursor)
source.setCursor(originalCursor);
if (destination instanceof JComponent) {
((JComponent) destination).setAutoscrolls(autoscrolls);
}
// Layout the components on the parent container
if (autoLayout) {
if (destination instanceof JComponent) {
((JComponent) destination).revalidate();
} else {
destination.validate();
}
}
}
}
What should I do with this code (or the other GUI's building code) to make me able to drag and drop components with children?
You have an adaptation of a ComponentMover by #camickr. The original and your version work fine with components that have children. Perhaps the problem is elsewhere. Consider posting an MCVE that illustrates the problem.
Here is a simple demo:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestMove extends JPanel{
public TestMove() {
setLayout(null);
JPanel panel = new JPanel();
panel.add(new JLabel("label"));
panel.add(new JButton("button"));
panel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
panel.setBounds(50, 50, 200, 50);
add(panel);
ComponentMover cm = new ComponentMover();
cm.registerComponent(panel);
}
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
TestMove panel = new TestMove();
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
});
}
}
Im making a quiz application. And when a team pushed their button, they aren't allowed to still see the question or see the video/audio piece. This kind of information is displayed in the quizview ( this is a jpanel ) added to a parent JFrame. What i'm trying to do is minimize the JFrame when a button is pushed from the teams. This works perfectly. If a button is pushed the administator get a pop up in his view. If the answer is incorrect the JFrame should be maximized again. So when he pushes a button if the answer is incorrect, a boolean will be set on true in the quiz model ( $maximize ). We update the views then. In the update of the view im checking if the boolean is set on true. If it is true, i call the maximize method. And maximize it again when the answer is wrong. Minimizing works perfectly, but maximizing not.
Anyone knows what's wrong?
This is my code in the view, this view is a JPanel in the bigger JFrame, where the maximizing happens :
public void update(Observable arg0, Object arg1) {
$question = (Question) arg1;
if(((QuizModel) getModel()).getMaximize()) /* Only maximize the JFrame when needed */
maximizeFrame(); /* Maximize the frame first */
repaint();
}
/**
* Maximize the parent JFrame so the teams can see the question
*/
protected void maximizeFrame() {
System.out.println("MAXIMIZE");
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
topFrame.setState(JFrame.MAXIMIZED_BOTH);
}
The minimizing occurs when a team pushed their button, here is the code :
/**
* If a button gets pressed we call this function
* #param team the team that pressed their button
*/
protected void buttonPressed(int team) {
/* Check if a button is pressed */
if(((QuizModel) getModel()).getTeamPressed() > 0)
$isPressed = true;
else
$isPressed = false;
/* If there hasn't been pressed yet and the question is not null */
if(!$isPressed && $question != null){
minimizeFrame(); /* Minimize the frame */
/* If this question has a media path we need to pause the audio/video, we also check if the user has installed vlcplayer and selected the right path */
if($question.getMediaPath() != null && QuizSoftwareModel.$vlcPath != null)
((QuizController)getController()).pause(); /* Pause the video */
/* Give a pop up message to the admin that a team has pushed their button */
((QuizController)getController()).showScoreView(team);
}
}
/**
* Minimize the parent JFrame so the teams can't see the question anymore
*/
protected void minimizeFrame() {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
topFrame.setState(JFrame.ICONIFIED);
}
[EDIT] Reduced the code.
Thanks!
The solution is using topFrame.setExtendedState(JFrame.MAXIMIZED_BOTH); instead of setState.
Setstate only sets the state of the current frame, because i needed the parent frame i needed to use setExtendedState.
Also missed some booleans to maximize/minimize when needed.
I have a Panel whose size needs to be changed for better view as i am loading lots of different widgets inside it. i went on using a Resizable Panel in GWT. It was all working fine.
My Question is : How can i implement it for Touch Enabled Devices like Android Tablets, iPads etc.
The Resize Panel uses Mouse Drag Events i hope. So how can i implement the same for Touch Events.
I have seen GWT-DND API where it provides Resibale Panels and was working in Touch Also.
But it will be a more tedious Task for me if i use it.
Can Anyone help?
Finally i figured it out. It was quite Simple, Just Added Touch Handlers similar to Mouse Events that i used.
ONTOUCHSTART = ONMOUSEDOWN
ONTOUCHMOVE = ONMOUSEMOVE
ONTOUCHEND = ONMOUSEUP
ONTOUCHCANCEL = ONLOSECAPTURE
ResizePanel.java
/**
* Abstract base class for {#link VerticalResizePanel}.
*/
abstract class ResizePanel extends Panel implements HasResizeHandlers {
/* **************************************** */
// Private Static Fields
/* **************************************** */
/**
* The element that masks the screen so we can catch mouse events over
* iframes.
*/
private static Element glassElem = null;
/** The handler manager for our events. */
/* **************************************** */
// Private Fields
/* **************************************** */
// The elements containing the widgets.
/** The elements. */
private final Element[] elements = new Element[1];
/** The handler manager for our events. */
private final EventBus resizeHandlerManager = new SimpleEventBus();
// Indicates whether drag resizing is active.
/** The is resizing. */
private boolean isResizing = false;
// The element that acts as the splitter.
/** The split elem. */
private final Element splitElem;
// The enclosed widgets.
/** The widgets. */
private final Widget[] widgets = new Widget[2];
/* **************************************** */
// Constructors
/* **************************************** */
/**
* Initializes the split panel.
*
* #param mainElem
* the root element for the split panel
* #param splitElem
* the element that acts as the splitter
* #param headElem
* the element to contain the top or left most widget
*/
ResizePanel(final Element mainElem, final Element splitElem,final Element headElem) {
this.setElement(mainElem);
this.splitElem = splitElem;
this.elements[0] = headElem;
this.sinkEvents(Event.MOUSEEVENTS | Event.ONLOSECAPTURE | Event.TOUCHEVENTS | Event.ONTOUCHCANCEL);
if (ResizePanel.glassElem == null) {
ResizePanel.glassElem = DOM.createDiv();
ResizePanel.glassElem.getStyle()
.setProperty("position", "absolute");
ResizePanel.glassElem.getStyle().setProperty("top", "0px");
ResizePanel.glassElem.getStyle().setProperty("left", "0px");
ResizePanel.glassElem.getStyle().setProperty("margin", "0px");
ResizePanel.glassElem.getStyle().setProperty("padding", "0px");
ResizePanel.glassElem.getStyle().setProperty("border", "0px");
// We need to set the background color or mouse events will go right
// through the glassElem. If the SplitPanel contains an iframe, the
// iframe will capture the event and the slider will stop moving.
ResizePanel.glassElem.getStyle().setProperty("background", "white");
ResizePanel.glassElem.getStyle().setProperty("opacity", "0.0");
ResizePanel.glassElem.getStyle().setProperty("filter",
"alpha(opacity=0)");
ResizePanel.glassElem.setId("glassElementId");
}
}
/* **************************************** */
// Package Static Properties
/* **************************************** */
/**
* Returns the offsetHeight element property.
*
* #param elem
* the element
* #return the offsetHeight property
*/
static final int getOffsetHeight(final Element elem) {
return DOM.getElementPropertyInt(elem, "offsetHeight");
}
/**
* Returns the offsetWidth element property.
*
* #param elem
* the element
* #return the offsetWidth property
*/
static final int getOffsetWidth(final Element elem) {
return DOM.getElementPropertyInt(elem, "offsetWidth");
}
/**
* Adds zero or none CSS values for padding, margin and border to prevent
* stylesheet overrides. Returns the element for convenience to support
* builder pattern.
*
* #param elem
* the element
* #return the element
*/
static final Element preventBoxStyles(final Element elem) {
DOM.setIntStyleAttribute(elem, "padding", 0);
DOM.setIntStyleAttribute(elem, "margin", 0);
DOM.setStyleAttribute(elem, "border", "none");
return elem;
}
/**
* Convenience method to set bottom offset of an element.
*
* #param elem
* the element
* #param size
* a CSS length value for bottom
*/
static void setBottom(final Element elem, final String size) {
DOM.setStyleAttribute(elem, "bottom", size);
}
/**
* Sets the elements css class name.
*
* #param elem
* the element
* #param className
* the class name
*/
static final void setClassname(final Element elem, final String className) {
DOM.setElementProperty(elem, "className", className);
}
/**
* Convenience method to set the height of an element.
*
* #param elem
* the element
* #param height
* a CSS length value for the height
*/
static final void setHeight(final Element elem, final String height) {
DOM.setStyleAttribute(elem, "height", height);
}
/**
* Convenience method to set the left offset of an element.
*
* #param elem
* the element
* #param left
* a CSS length value for left
*/
static final void setLeft(final Element elem, final String left) {
DOM.setStyleAttribute(elem, "left", left);
}
/**
* Convenience method to set the right offset of an element.
*
* #param elem
* the element
* #param right
* a CSS length value for right
*/
static final void setRight(final Element elem, final String right) {
DOM.setStyleAttribute(elem, "right", right);
}
/**
* Convenience method to set the top offset of an element.
*
* #param elem
* the element
* #param top
* a CSS length value for top
*/
static final void setTop(final Element elem, final String top) {
DOM.setStyleAttribute(elem, "top", top);
}
/**
* Convenience method to set the width of an element.
*
* #param elem
* the element
* #param width
* a CSS length value for the width
*/
static final void setWidth(final Element elem, final String width) {
DOM.setStyleAttribute(elem, "width", width);
}
/* **************************************** */
// Public Properties
/* **************************************** */
/**
* Gets the element that is acting as the splitter.
*
* #return the element
*/
public Element getSplitElement() {
return this.splitElem;
}
/**
* Gets the value of resizeHandlerManager.
*
* #return Gets the value of resizeHandlerManager.
*/
public EventBus getResizeHandlerManager() {
return resizeHandlerManager;
}
/**
* Indicates whether the split panel is being resized.
*
* #return if the user is dragging the splitter, otherwise
*/
public boolean isResizing() {
return this.isResizing;
}
/* **************************************** */
// Public Static Methods
/* **************************************** */
/**
* Sets an elements positioning to absolute.
*
* #param elem
* the element
*/
static void addAbsolutePositoning(final Element elem) {
DOM.setStyleAttribute(elem, "position", "absolute");
}
/**
* Adds clipping to an element.
*
* #param elem
* the element
*/
static final void addClipping(final Element elem) {
DOM.setStyleAttribute(elem, "overflow", "hidden");
}
/**
* Adds as-needed scrolling to an element.
*
* #param elem
* the element
*/
static final void addScrolling(final Element elem) {
DOM.setStyleAttribute(elem, "overflow", "auto");
}
/**
* Sizes and element to consume the full area of its parent using the CSS
* properties left, right, top, and bottom. This method is used for all
* browsers except IE6/7.
*
* #param elem
* the element
*/
static final void expandToFitParentUsingCssOffsets(final Element elem) {
final String zeroSize = "0px";
ResizePanel.addAbsolutePositoning(elem);
ResizePanel.setLeft(elem, zeroSize);
ResizePanel.setRight(elem, zeroSize);
ResizePanel.setTop(elem, zeroSize);
ResizePanel.setBottom(elem, zeroSize);
}
/**
* Sizes an element to consume the full areas of its parent using 100% width
* and height. This method is used on IE6/7 where CSS offsets don't work
* reliably.
*
* #param elem
* the element
*/
static final void expandToFitParentUsingPercentages(final Element elem) {
final String zeroSize = "0px";
final String fullSize = "100%";
ResizePanel.addAbsolutePositoning(elem);
ResizePanel.setTop(elem, zeroSize);
ResizePanel.setLeft(elem, zeroSize);
ResizePanel.setWidth(elem, fullSize);
ResizePanel.setHeight(elem, fullSize);
}
/* **************************************** */
// Public Methods
/* **************************************** */
/** {#inheritDoc} */
#Override
public void add(final Widget widget) {
boolean canAddWidget = false;
for (int index = 0; index < this.widgets.length; index++) {
if (this.getWidget(index) == null) {
this.setWidget(index, widget);
canAddWidget = true;
break;
}
}
if (!canAddWidget) {
throw new IllegalStateException(
"A Resizable panel can only contain two Widgets.");
}
}
/** {#inheritDoc} */
public HandlerRegistration addResizeHandler(final ResizeEventHandler handler) {
return this.resizeHandlerManager.addHandler(ResizeEvent.TYPE, handler);
}
/** {#inheritDoc} */
#Override
public Iterator<Widget> iterator() {
return ResizableControlIterator
.createWidgetIterator(this, this.widgets);
}
/** {#inheritDoc} */
#Override
public void onBrowserEvent(final Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
final Element target = DOM.eventGetTarget(event);
if (DOM.isOrHasChild(this.splitElem, target)) {
this.startResizingFrom(DOM.eventGetClientX(event) - this.getAbsoluteLeft(),DOM.eventGetClientY(event) - this.getAbsoluteTop());
DOM.setCapture(this.getElement());
DOM.eventPreventDefault(event);
}
break;
case Event.ONMOUSEUP:
if (this.isResizing()) {
// The order of these two lines is important. If we release
// capture
// first, then we might trigger an onLoseCapture event
// before we set
// isResizing to false.
DOM.releaseCapture(this.getElement());
this.splitPositionSetDone();
if (this.isResizing()) {
this.stopResizing();
}
}
break;
case Event.ONMOUSEMOVE:
if (this.isResizing()) {
assert DOM.getCaptureElement() != null;
this.onSplitterResize(DOM.eventGetClientX(event) - this.getAbsoluteLeft(),DOM.eventGetClientY(event) - this.getAbsoluteTop());
DOM.eventPreventDefault(event);
}
break;
// IE automatically releases capture if the user switches
// windows, so we
// need to catch the event and stop resizing.
case Event.ONLOSECAPTURE:
if (this.isResizing()) {
this.stopResizing();
}
break;
case Event.ONTOUCHSTART:
final Element touchableTarget = DOM.eventGetTarget(event);
if (DOM.isOrHasChild(this.splitElem, touchableTarget)) {
this.startResizingFrom((event.getTouches().get(0).getClientX() - this.getAbsoluteLeft()),(event.getTouches().get(0).getClientY() - this.getAbsoluteTop()));
DOM.setCapture(this.getElement());
event.preventDefault();
}
break;
case Event.ONTOUCHMOVE:
if (this.isResizing()) {
assert DOM.getCaptureElement() != null;
this.onSplitterResize((event.getTouches().get(0).getClientX() - this.getAbsoluteLeft()),(event.getTouches().get(0).getClientY() - this.getAbsoluteTop()));
event.preventDefault();
}
break;
// IE automatically releases capture if the user switches
// windows, so we
// need to catch the event and stop resizing.
case Event.ONTOUCHEND:
if (this.isResizing()) {
// The order of these two lines is important. If we release
// capture
// first, then we might trigger an onLoseCapture event
// before we set
// isResizing to false.
DOM.releaseCapture(this.getElement());
this.splitPositionSetDone();
if (this.isResizing()) {
this.stopResizing();
}
}
break;
case Event.ONTOUCHCANCEL:
if (this.isResizing()) {
this.stopResizing();
}
break;
default:
break;
}
super.onBrowserEvent(event);
}
/** {#inheritDoc} */
#Override
public boolean remove(final Widget widget) {
if (widget != null) {
for (int index = 0; index < this.widgets.length; index++) {
if ((this.widgets[index] == widget)) {
this.setWidget(index, null);
return true;
}
}
}
return false;
}
/**
* Moves the position of the splitter.
*
* #param size
* the new size of the left region in CSS units (e.g. "10px",
* "1em")
*/
public abstract void setSplitPosition(String size);
/**
* Split position set done.
*
*/
public abstract void splitPositionSetDone();
/**
* Called on each mouse drag event as the user is dragging the splitter.
*
* #param x
* the x coordinate of the mouse relative to the panel's extent
* #param y
* the y coordinate of the mouse relative to the panel's extent
*/
abstract void onSplitterResize(int x, int y);
/**
* Called when the user starts dragging the splitter.
*
* #param x
* the x coordinate of the mouse relative to the panel's extent
* #param y
* the y coordinate of the mouse relative to the panel's extent
*/
abstract void onSplitterResizeStarted(int x, int y);
/* **************************************** */
// Protected Methods
/* **************************************** */
/**
* Gets the content element for the given index.
*
* #param index
* the index of the element, only 0 and 1 are valid.
* #return the element
*/
protected Element getElement(final int index) {
return this.elements[index];
}
/**
* Gets one of the contained widgets.
*
* #param index
* the index of the widget, only 0 and 1 are valid.
* #return the widget
*/
protected Widget getWidget(final int index) {
return this.widgets[index];
}
/**
* <b>Affected Elements:</b>
* <ul>
* <li>-splitter = the container containing the splitter element.</li>
* </ul>
*
* #param baseId
* The base id.
* #see UIObject#onEnsureDebugId(String)
*/
#Override
protected void onEnsureDebugId(final String baseId) {
super.onEnsureDebugId(baseId);
UIObject.ensureDebugId(this.splitElem, baseId, "splitter");
}
/**
* Sets one of the contained widgets.
*
* #param index
* the index, only 0 and 1 are valid
* #param widget
* the widget
*/
protected final void setWidget(final int index, final Widget widget) {
final Widget oldWidget = this.widgets[index];
// Validate.
if (oldWidget == widget) {
return;
}
// Detach the new child.
if (widget != null) {
widget.removeFromParent();
}
// Remove the old child.
if (oldWidget != null) {
// Orphan old.
try {
this.orphan(oldWidget);
} finally {
// Physical detach old.
DOM.removeChild(this.elements[0], oldWidget.getElement());
this.widgets[index] = null;
}
}
// Logical attach new.
this.widgets[index] = widget;
if (widget != null) {
// Physical attach new.
DOM.appendChild(this.elements[0], widget.getElement());
// Adopt new.
this.adopt(widget);
}
}
/* **************************************** */
// Private Methods
/* **************************************** */
/**
* Start resizing from.
*
* #param x
* the x coordinate of the mouse relative to the panel's extent
* #param y
* the y coordinate of the mouse relative to the panel's extent
*/
public void startResizingFrom(final int x, final int y) {
this.isResizing = true;
this.onSplitterResizeStarted(x, y);
// Resize glassElem to take up the entire scrollable window area
final int height = RootPanel.getBodyElement().getScrollHeight() - 1;
final int width = RootPanel.getBodyElement().getScrollWidth() - 1;
ResizePanel.glassElem.getStyle().setProperty("height", height + "px");
ResizePanel.glassElem.getStyle().setProperty("width", width + "px");
RootPanel.getBodyElement().appendChild(ResizePanel.glassElem);
}
/**
* Stop resizing.
*/
void stopResizing() {
this.isResizing = false;
// FIXME:: Why is the remove causing error.
try {
RootPanel.getBodyElement().removeChild(ResizePanel.glassElem);
} catch (final Exception e) {
GWT.log("Got error removing the glassElem: " + e);
}
}
}
Also Adding my Event And Event Handlers
ResizeEvent.java
/**
* When panels (Ex: VerticalSplitPanel) are resized, adjust the positions.
*/
public class ResizeEvent extends GwtEvent<ResizeEventHandler> {
/* **************************************** */
// Public Static Fields
/* **************************************** */
/** The Constant TYPE. */
public static final Type<ResizeEventHandler> TYPE = new Type<ResizeEventHandler>();
/* **************************************** */
// Private Fields
/* **************************************** */
/** The split size. */
private final int splitSize;
/* **************************************** */
// Constructors
/* **************************************** */
/**
* Instantiates a new view set event.
*
* #param splitSize
* The split size.
*/
public ResizeEvent(final int splitSize) {
this.splitSize = splitSize;
}
/* **************************************** */
// Public Properties
/* **************************************** */
/** {#inheritDoc} */
#Override
public Type<ResizeEventHandler> getAssociatedType() {
return ResizeEvent.TYPE;
}
/**
* Gets the top position.
*
* #return The split position.
*/
public int getSplitSize() {
return splitSize;
}
/* **************************************** */
// Protected Methods
/* **************************************** */
/** {#inheritDoc} */
#Override
protected void dispatch(final ResizeEventHandler handler) {
handler.onResize(this);
}
}
ResizeEventHandler.java
/**
* The Interface ResizeEventHandler.
*/
public interface ResizeEventHandler extends EventHandler {
/**
* On move.
*
* #param event
* The event.
*/
void onResize(ResizeEvent event);
}