How to inject GWT Activity#start with a specific Widget? - java

I have the following parent container:
public class ParentContainer extends Composite {
// Contains a bunch of TextButtons (RedButton, GreenButton, etc.).
private LayoutPanel buttonPanel;
// When user clicks a TextButton inside the buttonPanel,
// it changes the content of this contentPanel.
private LayoutPanel contentPanel;
}
So when the user clicks one of the TextButtons inside the buttonPanel, the contentPanel's contents change. I am trying to get each TextButton click to be remembered in history, using the Activities/Places framework. So, if the user clicks the "Red", "Green" and "Blue" buttons respectively, the contentPanel will change three times, and then they can click the Back/Forward browser history buttons and keep moving back and forth in history (and "replaying" the button clicks over and over again, etc.).
I also have the following classes:
com.mywebapp
MainModule.gwt.xml
com.mywebapp.client
MainModule
com.mywebapp.client.places
RedButtonPlace
GreenButtonPlace
BlueButtonPlace
... 1 place for all buttons
com.mywebapp.client.activities
RedButtonActivity
GreenButtonActivity
BlueButtonActivity
... 1 activity for all buttons
com.mywebapp.client.ui
ParentContainer
RedButton
GreenButton
BlueButton
BlackButton
PurpleButton
OrangeButton
I am planning on wiring things up such that:
PlaceController.goTo(new RedButtonPlace()) eventually routes to the RedButtonActivity
PlaceController.goTo(new GreenButtonPlace()) eventually routes to the GreenButtonActivity
etc. (every button has a place and activity per its color)
What I'm stuck on is: if I call PlaceController.goTo(new RedButtonPlace()) from inside a RedButton click handler, how and where do I instruct RedButtonActivity to update contentPanel? For instance:
public class RedButton extends TextButton {
// ... bunch of stuff, nevermind why I am extending TextButton
// this is just to help me connect all the major dots of GWT!
public RedButton() {
this.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// If the RedButton is clicked, we want all the content in RedButtonActivity#RedButtonView
// to go inside ParentContainer#contentPanel.
PlaceController.goto(new RedButtonPlace());
}
});
}
}
public class RedButtonActivity extends AbstractActivity {
public interface RedButtonView extends IsWidget {
// Whatever the RedButton expects to be able to display.
}
private RedButtonView view;
#Override
public void start(AcceptsOneWidget panel, EventBus eventBus) {
// Probably injected via GIN.
view = somehowInjectTheView();
panel.setWidget(view);
}
}
That last line is the key here: panel.setWidget(view). How do we make sure that panel is the ParentContainer#contentPanel? Thanks in advance!
Edit: Per one answer suggests, here is a code update:
public class ParentContainer extends Composite {
// All the stuff that's up above in the first parent container.
public ParentContainer() {
super();
// Again, via GIN.
ActivityManager redButtonActivityManager = getSomehow();
redButtonActivityManager.setDisplay(contentPanel);
}
}
If this is the correct way, then I assume when the start(AcceptsOneWidget panel, EventBus eventBus) method is called, the redButtonActivityManager knows to inject the correct display for the panel argument?

You would pass the ParentContainer#contentPanel to the setDisplay() method of your ActivityManager as part of the manager's initialization.

Related

Adapter pattern with Buttons, adaptor class has to know which button was pressed

This is an actionPerformed in a Swing panel with custom buttons from a framework which scrambles their classes so all methods are a():String or b():void and there is no way to make out what it actually is.
I got a compiler error becaus when I inherit this button class the compiler find a():void an a():String which is not allowed in Java. My solution was to use the adapter pattern like this:
public abstract class FactoryButton {
private CustomButton button;
public FactoryButton(int width, int height) {
button = new DynButton();
button.setSize(width, height);
}
public DynButton getButton() {
return button;
}
}
So my FactoryButton has the CustomButton class as a private member. The FactoryButton is the parent of another Button class named FactorySelectionButton
which has an action performed where I used to be able to get the source of the event:
#Override
public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource() instanceof FactorySelectionButton) {
// User selected a factory
selectedItem = ((FactorySelectionButton) arg0.getSource()).getFactory();
// Close the screen, so control returns back to the parent window
cancel();
} else {
// other buttons implementation
}
}
But now since I solved one problem with the adapter pattern I have another the arg0.getSource() no longer gives me the FactorySelectionButton but it now gives a CustomButton which gives me no way to know which custom button is pressed.
The reason for not throwing away the custom button is that I am bound to the framework, I have to use it and the amount of factories can grow so I don't want hardcoded buttons.
So anyone have an idea on how I can fix this?
I found a way around it by looping over all my components and checking whether they have the button I need and they double checking whether it's really an instance of the class I want.
#Override
public void actionPerformed(ActionEvent arg0) {
for (FactoryButton component : components) {
if(component.getButton().equals(arg0.getSource()) && component instanceof FactorySelectionButton)
selectedItem = ((FactorySelectionButton) component).getFactory();
return;
}
//other buttons implementation
}

Two different buttons in one Panel in my own Component

I'm trying to create JPanel with two different buttons which one of them increasing and second decreasing size of text or window. I have class with button declaration. Everything is working when I put these buttons on JFrame separately.
I don't know how to get Action Listener in JPanel of each buttons. All I possibly do is listener of mouse click on JPanel...
Could you help me? I'm really begginer with coding so be polite please :]
public class ButtonMy extends Component {
private ButtonIncrease increase;
private PropertyChangeSupport propertyChangeSupport;
public ButtonMy() {
setPreferredSize(new Dimension(30,30));
kolor = Color.blue;
setForeground(kolor);
propertyChangeSupport = new PropertyChangeSupport(this);
increase = ButtonIncrease.Powieksz;
}
public ButtonIncrease getIncrease() {
return increase;
}
public void setIncrease(ButtonIncrease increase) {
ButtonIncrease oldIncrease = this.increase;
this.increase = increase;
propertyChangeSupport.firePropertyChange("increase", oldIncrease, increase);
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
There is JPanel for bind 2 buttons. Here is the biggest problem :/ I'm lack of ideas.
public class ButtonB extends JPanel implements ActionListener{
public ButtonMy b1 = new ButtonMy();
public ButtonMy b2 = new ButtonMy();
public ButtonB (){
init();
}
public final void init(){
setLayout(new GridLayout(1,2));
this.przycisk1.setIncrease(ButtonIncrease.Powieksz);
this.przycisk2.setIncrease(ButtonIncrease.Zmniejsz);
add(b1);
add(b2);
}
}
JFrame where I test this component is very common. Code below shows only function for inc and dec size when separate button is clicked (not in JPanel).
private void buttonMy3MouseClicked(java.awt.event.MouseEvent evt) {
switch(buttonMy3.getIncrease()) {
case Powieksz: setSize(1);
break;
case Zmniejsz: setSize(0);
break;
}
}
I didn't paste full of my code. There some of math functions left which I think they are not needed here (setSize for example).
I'm not sure if i understand the problem correctly but I think under the actionListener class you should have a method called actionPerformed& it will say that if button1 is clicked increase the number, if button2 is clicked decrease the number:
public void actionPerformed( ActionEvent event ) {
if (event.getSource()== b1) // your "increase size" code
if(event.getSource()== b2)// your "decrease size" code
}
button listeners are actually different from mouse listeners; buttons implements ActionListeners and have the actionPerformed method with event variable. you could handle the event by:
getSource() -this method is inherited from java.util.EventObject and returns the OBJECT on which the event initially occurred (the button itself)
or by getActionCommand() -this method is available to action events, or any event that inherits from ActionEvent and returns the command STRING associated with this action.
however mouse listeners implements MouseListener and has a lot of methods depending on what the mouse does (pressed, clicked, released, etc.).

JavaFX subclassed Button - How to make Label update work?

I want to have several JavaFX Buttons that update one Label in my Application with text. For testing purposes it's just Button Text.
What I did at first worked fine and looked like this:
String Text = "...";
public void kons() {
System.out.println("Works...");
System.out.println(Text);
Tekst.setText(Text);
Button G4 = new Button("Spadantes");
G4.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Text = G4.getText();
kons();
}
});
Then I decided to stylize my buttons with CSS and because I wanted to have several groups of buttons stylized in different way I subclassed JavaFX Button class in this way:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
Which still worked. But now I want my event handler to be moved to Button subclass (to avoid copy-pasting exactly same code into each and every button of mine). What I did looks like this:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Main.Text = getText();
Main.kons();
}
});
}
}
Main is my extend Application class
Tekst is my label.
And sadly it throws me exception about calling non-stathic method and variable from static context. From what I understand instances are static and definitions are non-static. I tried to change everything "in the way" to static but it gives me red wall of errors after clicking button (nothing in compilation process). I also tried to call instance of my Application somehow but I have no idea how (from what I understand extend Application class intantiates itself on it's own while starting program so there's no "name" by which I can call it's Label.
What I'm looking for is "quick and dirty solution" to be able to use subclassed buttons (or other sliders, text-fields, etc.) that can call a method that updates something "on screen".
[EDIT] I'm using newest Java there is of course. In case it matters.
Instead of subclassing, why not just write a utility method that creates the buttons for you? I would also not recommend making the text variable an instance variable: just reference the Label directly.
public class SomeClass {
private Label tekst ;
// ...
private Button createButton(String buttonText) {
Button button = new Button(buttonText);
button.getStylesheets().add("Buttons.css") ;
button.setOnAction(e -> tekst.setText(buttonText));
return button ;
}
}
Then, from within the same class, when you need one of those buttons you just do
Button button = createButton("Text");
If you really want to subclass (which just seems unnecessary to me), you need to pass a reference to the label to the subclass:
public class LabelUpdatingButton extends Button {
public LabelUpdatingButton(String text, Label labelToUpdate) {
super(text);
getStylesheets().add("Buttons.css");
setOnAction(e -> labelToUpdate.setText(getText()) );
}
}
Then from your class that assembles the UI you can do
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Label tekst = new Label();
Button someButton = new LabelUpdatingButton("Button text", tekst);
// etc...
}
}
But again, creating a subclass that does nothing other than define a constructor that calls public API methods is redundant, imo.
Also, it's a bit unusual to create an entire stylesheet just for your buttons. Typically you would set a style class on the Button:
button.getStyleClass().add("my-button-class");
and then in the stylesheet you add to the Scene do
.my-button-class {
/* styles for this type of button */
}

Handling GWT Click Events In a Different Method

Basically what I am trying to do here is handle click events which panel is suppose to appear to depending on which button is click. For example, if we click button one, the corresponding panel will pop up. But the panel and click event does not know anything about each other. I believe its called anonymous class. I am having trouble trying to implement this. What would be a good way to implement this?
This is my button click event class
public class buttonHandle extends Composite {
private static buttonHandleUiBinder uiBinder = GWT
.create(buttonHandleUiBinder.class);
#UiField Button button;
#UiField Button button_1;
interface buttonHandleUiBinder extends UiBinder<Widget, buttonHandle> {
}
public buttonHandle() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("button")
void onButtonClick(ClickEvent event) {
}
#UiHandler("button_1")
void onButton_1Click(ClickEvent event) {
}
}
This is the class where I am trying to add a new button everytime a button is clicked
public class PanelHandle extends Composite {
private AbsolutePanel absolutePanel = new AbsolutePanel();
public PanelHandle() {
initWidget(absolutePanel);
absolutePanel.setSize("1027px", "636px");
Label lblHello = new Label("Hello");
absolutePanel.add(lblHello, 47, 80);
Label lblHello_1 = new Label("Hello");
absolutePanel.add(lblHello_1, 232, 249);
// TODO Auto-generated constructor stub
}
public void buttonOne()
{
this.absolutePanel.clear();
Button but1 = new Button("button one");
this.absolutePanel.add(but1);
}
}
I tried something like this, but it does not update the panel with a new button
private PanelHandle pHandle = new PanelHandle();
private static buttonHandleUiBinder uiBinder = GWT
.create(buttonHandleUiBinder.class);
#UiField Button button;
#UiField Button button_1;
interface buttonHandleUiBinder extends UiBinder<Widget, buttonHandle> {
}
public buttonHandle() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("button")
void onButtonClick(ClickEvent event) {
Window.alert("hello buttone clicked");
pHandle.buttonOne();
}
#UiHandler("button_1")
void onButton_1Click(ClickEvent event) {
}
}
So far I tried to call the method in my PanelHandle class, but I am encountering errors such stack overflow. In another method I tried, I am unable to update the panel when I add.
I am using a button here instead of panel just for testing until I understand the logic.
Thank You for you help!
Create an own (gwt)event when a button is clicked. You can fire your own event wherever you want. Fill the event with the information you need.
Next add the class which have to handle this event to the gwt eventbus. If a event is fired, your handle class catch the event and work with the data from the event.
This could be helpful: How to use the GWT EventBus

Allow parent to handle mouse event

I added a JPanel to a JRadioButton - so that I may display whatever I want in the radio button.
This all worked as expected. But to allow for text wrapping, I used a JTextArea and added it to the JPanel contained within the radio button.
Now I have an issue where, if the user clicks on the JTextArea, then the JTextArea consumes the mouseEvent and as a result there is no response from the radio button (it doesn't 'select').
Is there a way get the JTextArea to ignore the mouse click, so that the parent may handle it instead?
I tried add the JTextArea's listeners to the radioButton instead.
I also tried to remove its listeners completely, but both these attempts failed.
Anyone have any suggestions?
Strong beware
Most JSomething are not meant to be used as containers even though it's possible - the outcome of doing it anyway is more or less visually and behaviourally undetermined!
That said, did it recently, to implement something similar to a Windows task dialog. If the requirement includes keeping the button clickable (and why else would you mis-use it as a container :-) the main problem (layout apart) is to make all added components completely mouse-transparent. Which is more difficult than can be expected. The minimum is to not allow adding of mouseListeners and disable the acceptance of mouseEvents:
final JTextArea area = new JTextArea("replacement ..") {
#Override
public synchronized void addMouseListener(MouseListener l) {
LOG.info("adding here ...?");
}
#Override
public synchronized void addMouseMotionListener(
MouseMotionListener l) {
}
#Override
public synchronized void addMouseWheelListener(
MouseWheelListener l) {
}
#Override
public void addNotify() {
disableEvents(AWTEvent.MOUSE_EVENT_MASK |
AWTEvent.MOUSE_MOTION_EVENT_MASK |
AWTEvent.MOUSE_WHEEL_EVENT_MASK);
super.addNotify();
}
};
Plus make sure it's not focusable
area.setEditable(false);
area.setFocusable(false);
area.setRequestFocusEnabled(false);
Plus unregister dragging and tooltips
ToolTipManager.sharedInstance().unregisterComponent(area);
area.setDragEnabled(false);
Nevertheless, there might still be surprises ahead, f.i. call the following twice (that is disable and enable again), which will internally re-enable mouseEvent:
area.setAutoscrolls(!area.getAutoscrolls());
So at the end of the day, we might get away with it - but never be entirely certain that we succeeded.
What about this? Create and add your own MouseListener to TextArea
JPanel p = new JPanel();
JTextArea t = new JTextArea("line \n line");
t.addMouseListener(new MyMouseListener());
p.add(t);
jRadioButton1.add(p);
jRadioButton1.addMouseListener(new MyRadioButtonMouseListener());
And in the MyMouseListener Dispatch event
private class MyMouseListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
Component source = (Component) e.getSource();
source.getParent().getParent().dispatchEvent(e); // 2x getParent() because JTextArea->JPanel->JRadio
}
.
.
.
}
And finally RadioButtonMouseListener
private class MyRadioButtonMouseListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("CLICK ON RADIOBUTTON !!");
}
.
.
.
}

Categories

Resources