Form title is written twice

48 views
Skip to first unread message

howud...@gmail.com

unread,
Sep 20, 2016, 9:53:46 PM9/20/16
to CodenameOne Discussions
When using a side menu and right bar and toastbar, setting the title of the window results in overwritten text:
The below code demos the problem.   Click on the filter button (far right, then click on apply in the dialog).  The result is below


package com.mycompany.myapp;


import com.codename1.components.ToastBar;
import com.codename1.ui.Command;
import com.codename1.ui.Display;
import com.codename1.ui.FontImage;
import com.codename1.ui.Toolbar;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.table.Table;


public class FrmClients extends com.codename1.ui.Form {
 
protected Table table = null;
 
protected DlgClientFilter dlgFilter = new DlgClientFilter();
 
ToastBar.Status status = ToastBar.getInstance().createStatus();
 
 
public FrmClients() {
 initManualComponents
();
 
}


 
protected void initManualComponents() {
       
Toolbar.setGlobalToolbar(true);
        setLayout
(new BoxLayout(BoxLayout.Y_AXIS));
 setTitle
("Clients");
 setName
("FrmClients");


 
// sidebar
 
if (getToolbar() == null) {
 setToolbar
(new Toolbar());
 
}
 getToolbar
().addCommandToSideMenu(new Command("Dashboard") {
 
public void actionPerformed(com.codename1.ui.events.ActionEvent ev) {
 
}
 
});
 
 
Command cmdFilter = new Command("", FontImage.createMaterial(FontImage.MATERIAL_FILTER_LIST, UIManager.getInstance().getComponentStyle("Command"), 5)) {
 
public void actionPerformed(com.codename1.ui.events.ActionEvent ev) {
 onFilter
();
 
}
 
};
 getToolbar
().addCommandToRightBar(cmdFilter);
 
    table
= new Table();
   
this.add(table);
 
}


 
public void refresh() {
 status
.setMessage("Test");
 status
.setProgress(0);
 status
.show();
 
 loadClients
(status);
 
}


 
protected void loadClients(ToastBar.Status prog) {
 prog
.clear();
 setTitle
("Test Done");
 
return;
 
}
 
 
protected void onFilter() {
 dlgFilter
.show(10, 0, (int)(Display.getInstance().getDisplayWidth()*.5), 0);
 refresh
();
 
}
}

Shai Almog

unread,
Sep 21, 2016, 12:51:46 AM9/21/16
to CodenameOne Discussions, howud...@gmail.com
I'm guessing this relates to dlgFilter blocking the EDT and disrupting the event processing.

howud...@gmail.com

unread,
Sep 21, 2016, 9:24:36 AM9/21/16
to CodenameOne Discussions, howud...@gmail.com
except that hitting apply disposes the dialog and should release the edt.  (I forgot to include DlgFilter, here it is)

package com.mycompany.myapp;


import com.codename1.ui.Button;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.FontImage;
import com.codename1.ui.Label;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.table.TableLayout;


public class DlgClientFilter extends Dialog {
 
public boolean Cancelled = false;
 
protected TableLayout layout = new TableLayout(10,3);
 
protected Button btnApply = new Button(FontImage.createMaterial(FontImage.MATERIAL_DONE, UIManager.getInstance().getComponentStyle("Command"), 5));
 
protected Button btnClose = new Button(FontImage.createMaterial(FontImage.MATERIAL_CLEAR, UIManager.getInstance().getComponentStyle("Command"), 5));


 
public DlgClientFilter() {
        initManualComponents
();
   
}
   
   
protected void initManualComponents() {
   
this.setLayout(layout);
   
this.setUIID("Form");
   
this.setDialogUIID("Form");
       
this.getStyle().setBgTransparency(255);
       
this.getDialogStyle().setBgTransparency(255);
    add
(layout.createConstraint().widthPercentage(30), new Label(""));
    add
(layout.createConstraint().widthPercentage(55), new Label(""));
    add
(layout.createConstraint().widthPercentage(15), new Label(""));
   
Container cnt2 = new Container();
    cnt2
.add(btnApply);
    cnt2
.add(btnClose);
    btnApply
.addActionListener(evt -> onApply());
    btnClose
.addActionListener(evt -> onClose());
    add
(layout.createConstraint().horizontalSpan(3).horizontalAlign(Component.RIGHT), cnt2);
   
    add
(layout.createConstraint().horizontalSpan(3), new Label("Client Info"));
   
}
   
   
protected void onApply() {
   
Cancelled = false;
      dispose
();
   
}
   
   
protected void onClose() {
   
Cancelled = true;
    dispose
();
   
}


}

Shai Almog

unread,
Sep 21, 2016, 11:48:03 PM9/21/16
to CodenameOne Discussions, howud...@gmail.com
Try it without the dialog.
Try showing the dialog as modless.

howud...@gmail.com

unread,
Sep 22, 2016, 10:13:39 AM9/22/16
to CodenameOne Discussions, howud...@gmail.com
The title is displayed correctly when I dont show the dialog, obviously this is not a solution
The title is also correct when I show the dialog modeless.  This is a possible solution but requires now that I implement some form of a callback to inform the calling form that the dialog is disposed of.
The ideal solution would be to fix the bug that is causing the title to be displayed twice when the dialog is shown modal.

Shai Almog

unread,
Sep 23, 2016, 2:00:47 AM9/23/16
to CodenameOne Discussions, howud...@gmail.com
Not practical. You have a chain of calls that you implicitly rely on, we try to hide some of that complexity but obviously you have more going on.

howud...@gmail.com

unread,
Sep 23, 2016, 10:04:50 AM9/23/16
to CodenameOne Discussions, howud...@gmail.com
obviously I have more going on?

I would say obviously your framework has a bug.  I would say my use scenario is not that unusual...obviously
Displaying a dialog, and then when that dialog is disposed displaying a progress indication (toastbar) and then updating an element on the form is NOT unusual.
Fix it or dont fix it, I dont care.  Having bugs that programmers have to work around only hurts your product's reputation.

Peter

Shai Almog

unread,
Sep 24, 2016, 1:56:51 AM9/24/16
to CodenameOne Discussions, howud...@gmail.com
No.
I suggest re-reading the developer guide chapter on the EDT. And understanding exactly what invoke and block does.
We have bugs, this isn't one of them.

howud...@gmail.com

unread,
Sep 24, 2016, 11:37:44 AM9/24/16
to CodenameOne Discussions, howud...@gmail.com
I have read the developer guide, more times than I'd like to admit, although I must admit I haven't made it past miscellaneous functions.  In fact I can tell you that you have so far 26 navigation errors in your document and numerous typos as well as outdated code and samples that no longer work.  Dont believe me that's ok, here's the list of navigation errors:


Now getting back to getting some technical support.  I am mostly positive this is NOT and EDT problem.  For some reason you remove the center component from the title bar and never replace it.  This happens during the out animation of the toastbar.  stack:


Thread [EDT] (Suspended (breakpoint at line 202 in BorderLayout))
 
BorderLayout.removeLayoutComponent(Component) line: 202
 
Toolbar(Container).removeComponentImplNoAnimationSafety(Component) line: 929
 
Container$3.updateState() line: 913
 
Container$3(ComponentAnimation).updateAnimationState() line: 80
 
AnimationManager.updateAnimations() line: 69
 
FrmMain(Form).repaintAnimations() line: 1350
 
Display.edtLoopImpl() line: 1078
 
Display.invokeAndBlock(Runnable, boolean) line: 1204
 
Display.invokeAndBlock(Runnable) line: 1242
 
AnimationManager.addAnimationAndBlock(ComponentAnimation) line: 105
 
Container.animateHierarchy(int, boolean, int) line: 2476
 
Container.animateHierarchyAndWait(int) line: 2196
 
ToastBar.setVisible(boolean) line: 724
 
ToastBar.updateStatus() line: 468
 
ToastBar.removeStatus(ToastBar$Status) line: 680
 
ToastBar.access$700(ToastBar, ToastBar$Status) line: 76
 
ToastBar$Status.clear() line: 348
 
FrmMain.refresh() line: 73
 
FrmMain.onClick() line: 64
 
FrmMain$2.actionPerformed(ActionEvent) line: 52
 
EventDispatcher.fireActionEvent(ActionEvent) line: 349
 
Button.fireActionEvent(int, int) line: 403
 
Button.released(int, int) line: 442
 
Button.pointerReleased(int, int) line: 530
 
FrmMain(Form).pointerReleased(int, int) line: 2599
 
FrmMain(Form).pointerReleased(int, int) line: 2563
 
FrmMain(Component).pointerReleased(int[], int[]) line: 3154
 
Display.handleEvent(int) line: 2024
 
Display.edtLoopImpl() line: 1066
 
Display.mainEDTLoop() line: 995
 
RunnableWrapper.run() line: 120
 
CodenameOneThread.run() line: 176

Then when setTitle is called, the center component is null and a new component is created:

    public void setTitle(String title) {
        checkIfInitialized
();
       
Component center = ((BorderLayout) getLayout()).getCenter();
       
if (center instanceof Label) {
           
((Label) center).setText(title);
       
} else {
            titleComponent
= new Label(title);
            titleComponent
.setUIID("Title");
           
if (center != null) {
                replace
(center, titleComponent, null);
           
} else {
                addComponent
(BorderLayout.CENTER, titleComponent);
           
}
       
}
   
}

Using callSeriallyandWait on setTitle results in an error because we are already on the EDT.  Here is a full test sample.  It is not complicated. and has only the minimum required.  

package com.mycompany.myapp;

import com.codename1.components.ToastBar;
import com.codename1.ui.Button;
import com.codename1.ui.Command;
import com.codename1.ui.Component;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.Display;
import com.codename1.ui.FontImage;
import com.codename1.ui.Label;
import com.codename1.ui.TextArea;
import com.codename1.ui.Toolbar;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.table.Table;
import com.codename1.ui.table.TableLayout;

public class FrmMain extends com.codename1.ui.Form {
protected Container cntFixed = new Container(); // fixed panel
TableLayout layout = new TableLayout(3, 3);
ToastBar.Status status = ToastBar.getInstance().createStatus();
protected DlgClientFilter2 dlgFilter = new DlgClientFilter2();
protected Table table = null;

public FrmMain() {
this(com.codename1.ui.util.Resources.getGlobalResources());
}

public FrmMain(com.codename1.ui.util.Resources resourceObjectInstance) {
initManualComponents();
}

protected void initManualComponents() {
setLayout(new BoxLayout(BoxLayout.Y_AXIS));
setTitle("Clients");
setName("FrmClients");

// sidebar
if (getToolbar() == null) {
setToolbar(new Toolbar());
}
getToolbar().addCommandToSideMenu(new Command("Dashboard") {
public void actionPerformed(com.codename1.ui.events.ActionEvent ev) {
}
});

Command cmdFilter = new Command("", FontImage.createMaterial(FontImage.MATERIAL_FILTER_LIST,
UIManager.getInstance().getComponentStyle("Command"), 5)) {
public void actionPerformed(com.codename1.ui.events.ActionEvent ev) {
onClick();
}
};
getToolbar().addCommandToRightBar(cmdFilter);

table = new Table();
this.add(table);
}

protected void onClick() {
System.out.println(Display.getInstance().isEdt());
dlgFilter.show(10, 0, (int) (Display.getInstance().getDisplayWidth() * .5), 0);
refresh();
}

public void refresh() {
System.out.println(Display.getInstance().isEdt());
status.setMessage("Test");
status.setProgress(0);
status.show();

status.clear();
System.out.println(Display.getInstance().isEdt());
// This does not work as we are already on the EDT, so just call setTitle()
// Display.getInstance().callSeriallyAndWait(() ->  setTitle("Test Done"));
setTitle("Test Done");
}
public class DlgClientFilter2 extends Dialog {
protected TableLayout layout = new TableLayout(10,3);
protected Button btnApply = new Button(FontImage.createMaterial(FontImage.MATERIAL_DONE, UIManager.getInstance().getComponentStyle("Command"), 5));

protected TextArea taNotes = new TextArea() {

@Override
protected Dimension calcPreferredSize() {
return new Dimension(800, 500);
}
};

public DlgClientFilter2() {
       initManualComponents();
   }
   
   protected void initManualComponents() {
    this.setLayout(layout);

    taNotes.setPreferredSize(new Dimension(800, 500));
       
    Container content = getContentPane();
       content.add(layout.createConstraint().widthPercentage(33), new Label(""));
       content.add(layout.createConstraint().widthPercentage(33), new Label(""));
       content.add(layout.createConstraint().widthPercentage(33), new Label(""));

    Container cnt2 = new Container();
    cnt2.add(btnApply);
    btnApply.addActionListener(evt -> onApply());
    content.add(layout.createConstraint().horizontalSpan(3).horizontalAlign(Component.RIGHT), cnt2);
    content.add(layout.createConstraint().horizontalSpan(3), taNotes);

   }
   
   protected void onApply() {
    dispose();
   }
   
}
}


Shai Almog

unread,
Sep 25, 2016, 12:22:46 AM9/25/16
to CodenameOne Discussions, howud...@gmail.com

howud...@gmail.com

unread,
Sep 25, 2016, 9:46:52 AM9/25/16
to CodenameOne Discussions, howud...@gmail.com
Did you take the time to read my message?  Apparently not as you completely ignored the question.  

Shai Almog

unread,
Sep 26, 2016, 12:14:03 AM9/26/16
to CodenameOne Discussions, howud...@gmail.com
I answered your question just fine in the original form where I explained that this isn't a bug and provided 2 ways to resolve the issue which you didn't like.
I've spent a lot of time answering your questions despite your attitude.
Reply all
Reply to author
Forward
0 new messages