May I use DockLayoutPanel in DialogBox in GWT - gwt

I' m tying to make a dialog box that contains 3 parts: TextBox, DataGrid and Button. And I'm using DockLayoutPanel like that
<ui:style>
.panel {
width: 600px;
height: 500px;
}
</ui:style>
<g:HTMLPanel addStyleNames='{style.panel}'>
<g:DockLayoutPanel unit="PX">
<g:north size="45">
<g:TextBox>...
</g:north>
<g:south size="45">
<g:Button>...
</g:south>
<g:center>
<g:DataGrid>...
</g:center>
</g:DockLayoutPanel>
</g:HTMLPanel>
Here is my class
public class MyDialogBoxViewImpl extends DialogBox {
interface MyDialogBoxViewImplUiBinder extends
UiBinder<Widget, MyDialogBoxViewImpl> {
}
...
But the problem is that only TextBox is visible.
I'm not sure that it is properly to use DockLayoutPanel in DialogBox, but it is so suitable for my application. So can you help me with my issue and give me some advices how to replace DockLayoutPanel if it will need. Thanks.

Try setting explicitly the size of DockLayoutPanel.
For example:
<g:DockLayoutPanel unit="PX" width="100%" height="100%">

Your size values are "100%", but your unit is "PX". Try changing your unit to "PCT" for percentage width and height

Related

GWT - DataGrid table with Filter in the same view / panel

I'm trying to add a DataGrid on my view.
I know that a DataGrid can only stay in a Layout Panel, because of the ProvidesResize and RequiresResize interfaces.
The thing is, I want to add a filter on top of the DataGrid Table, and the filter can't have a fixed height, it could be bigger or smaller.
No Layout Panel would accept more then one child to be resized, but the LayoutPanel itself. But still, each layer needs a height to be set in percentage, and that's not OK as well.
If I change the DataGrid with a CellTable and then add both in a Flow Panel, the problem would be solved, but the table has to be scrollable.
What I would need is a FlowLayoutPanel but there is no such Panel in GWT
I was thinking that the only way would be to try to create a custom panel which would implement ProvidesResize and RequiresResize interfaces.
This is how it looks like using a LayoutPanel :
<g:layer left="2%" right="68%" top="2%" bottom="93%">
<g:Label ui:field="gridBlurb" addStyleNames="{res.viewStandardStyle.viewTitle}" />
</g:layer>
<g:layer left="2%" right="68%" top="9%" bottom="56%">
<g:SplitLayoutPanel>
<g:center>
<g:HTMLPanel>
<g:FlowPanel ui:field="criteriaPanel" visible="false" />
<g:FlowPanel>
<g:Button ui:field="refresh">
<ui:text from="{text.refreshButtonCaption}" />
</g:Button>
</g:FlowPanel>
</g:HTMLPanel>
</g:center>
</g:SplitLayoutPanel>
</g:layer>
<g:layer left="2%" right="2%" top="45%" bottom="5%">
<g:SplitLayoutPanel>
<g:center>
<c:DataGrid ui:field='table' />
</g:center>
</g:SplitLayoutPanel>
</g:layer>
<g:layer left='2%' right='2%' top="95%" bottom="0%">
<g:HTMLPanel>
<table style="width:100%">
<tr>
<td align='center'>
<c:SimplePager ui:field='pager' />
</td>
</tr>
</table>
</g:HTMLPanel>
</g:layer>
</g:LayoutPanel>
Can anyone help me with this ?
Many thanks in advance.
If you don't care about very old browsers, use flexbox CSS layout model - I use it with DataGrid (and for everything else) all the time.
Then you simply add display: flex; to your container (i.e. what you used LayoutPanel for), and then set flex-grow: 1 on your DataGrid. This will tell DataGrid to take all the available space after other widgets in the container have been rendered.
P.S. For the past few years I try to avoid LayoutPanels as much as possible for performance reasons, especially on mobile devices.
looks like the CSS did the trick.
Many thanks.
This is how it looks like :
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:c="urn:import:com.google.gwt.user.cellview.client">
<ui:with field='res' type='com.vsg.vraweb.client.resource.Resources' />
<ui:with field='text' type='com.vsg.vralang.client.GlobalConstants' />
<!--
CSS Tricks tutorial : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
1) 'display: flex;' - enables a flex context for all its direct children.
2) 'flex-direction: row | row-reverse | column | column-reverse;' - This establishes
the main-axis, thus defining the direction flex items are placed in the flex
container.
3) flex-grow: <number>; - This defines the ability for a flex item to grow if necessary.
-->
<ui:style>
.container {
display: flex;
flex-direction: column;
}
.dataGrid {
width: 100%;
flex-grow: 1;
}
</ui:style>
<g:FlowPanel addStyleNames="{style.container}">
<g:Label ui:field="gridBlurb" addStyleNames="{res.viewStandardStyle.viewTitle}" />
<g:HTMLPanel>
<g:FlowPanel ui:field="criteriaPanel" visible="false" />
<g:FlowPanel>
<g:Button ui:field="refresh">
<ui:text from="{text.refreshButtonCaption}" />
</g:Button>
</g:FlowPanel>
</g:HTMLPanel>
<c:DataGrid ui:field='table' addStyleNames="{style.dataGrid}"/>
<g:HTMLPanel>
<table style="width:100%">
<tr>
<td align='center'>
<c:SimplePager ui:field='pager' />
</td>
</tr>
</table>
</g:HTMLPanel>
</g:FlowPanel>
</ui:UiBinder>

#url of ImageResource in external ClientBundle, to be used in UiBinder

Is it possible to reference an ImageResource with #url in UiBinder, when the ImageResource and the UiBinder are not in the same package?
For example:
My shared ClientBundle :
package com.myproject.client.resources;
class SharedResources extends ClientBundle {
ImageResource myImage();
}
And, the UiBinder file in package com.myproject.client.anotherpackage
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field="res" type="com.myproject.client.resources.SharedResources"/>
<ui:style>
#url myImg {insert reference to res.myImage}
.theClass {
background: myImg no-repeat center center #d7d6d6;
width: 21px;
}
</ui:style>
<g:HTMLPanel styleName="{style.theClass}"/>
</ui:UiBinder>
I know I could move the CSS to com.myproject.client.resources and then I would have easy access to the myImage (since the CSS and myImage would be in the same package), but I would prefer to keep the CSS inside the UiBinder and reuse the shared myImage from within the UiBinder.
There's a discussion regarding this issue here, but it does not answer my question:
https://groups.google.com/forum/#!topic/google-web-toolkit/ExOJAEfQmkY
I reached the same problem and my solution was to use ui:image. This solution will not reuse and refer directly to the ClientBundle like I think you want, but it gives you the possibility of not moving your CSS, or copying the image to your folder, or creating a new ClientBundle.
The code is something like:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:with field="res" type="com.myproject.client.resources.SharedResources"/>
<ui:image field="resImage" src="../resources/image.png" />
<ui:style>
#url myImg resImage
.theClass {
background: myImg no-repeat center center #d7d6d6;
width: 21px;
}
</ui:style>
<g:HTMLPanel styleName="{style.theClass}"/>
</ui:UiBinder>
I kept the SharedResources reference just to illustrate using your example, but it isn't being used in this case.

GWT uibinder - how to specify such a simple layout?

I'm using GWT 2.5.1 with uibinder xml for specifying ui layouts.
Being a newbie in this, can't figure out how to specify even a simple layout:
I want the [Somelabel:] and [Button] to take the minimal required place, and [Textbox] to occupy the rest. Tried different approaches: placing them to HorizontalPanel, FlowPanel, even DockLayoutPanel. None of them satisfy my requirements: HorizontalPanel just divides parent container to three equal parts, FlowPanel gives no respect to element width, DockLayoutPanel wants me to manually calculate and specify the width of [Somelabel:] and [Button] and still doesn't work at all.
That is the basic ui layout task and I can't believe that GWT does not have a way to specify what I want without manual pixelwidth calculation. Most different UI tools have the simple way to specify it.
this lays them in equal cells:
<g:HorizontalPanel width="100%">
<g:Label>Somelabel:</g:Label>
<g:TextBox ui:field="someTextBox"/>
<g:Button ui:field="someButton" text="Button"/>
</g:HorizontalPanel>
this lays them in a weird way (whether "float: left" specified for label or not; whether "float: right" specified for button or not):
<g:FlowPanel width="100%">
<g:Label>Somelabel:</g:Label>
<g:TextBox ui:field="someTextBox"/>
<g:Button ui:field="someButton" text="Button"/>
</g:FlowPanel>
this wants me to specify pixels but doesn't even display them:
<g:DockLayoutPanel width="100%" height="90">
<g:east size="30"><g:Label>Somelabel:</g:Label></g:east>
<g:center><g:TextBox ui:field="someTextBox"/></g:center>
<g:west size="50"><g:Button ui:field="someButton" text="Button"/></g:west>
</g:DockLayoutPanel>
[no image because it doesn't display anything]
I'm kinda stuck because the only kind-of-working xml is the HorizontalPanel one and it does not do what I want.
UP: added screenshots and tried "float:" css styles (which didn't change anything).
UP2: got the picture I wanted using LayoutPanel and specifying pixelwidth of each layer.
<g:LayoutPanel width="100%" height="40px">
<g:layer width="100px" left="0">
<g:Label>Somelabel:</g:Label>
</g:layer>
<g:layer left="100px" right="200px">
<g:TextBox ui:field="someTextBox"/>
</g:layer>
<g:layer width="200px" right="0">
<g:Button ui:field="someButton" text="Button"/>
</g:layer>
</g:LayoutPanel>
But the xml looks ugly, forces me to calculate pixels manually, and to specify each width in two places. Can I somehow leave the pixelwidth calculations to framework and just specify "place it there and give it minimum place it wants"?
If you refer to the GWT docs [here][1] it mentions your exact problem. Try using FlowPanel with float : left CSS property as specified.
EDIT :
This worked for me
Ui-Binder
<g:FlowPanel width="100%" addStyleNames="myTable">
<g:FlowPanel addStyleNames="myTableRow">
<g:Label addStyleNames="myTableLabel">Somelabel:</g:Label>
<g:FlowPanel width="100%" addStyleNames="myTableCell">
<g:TextBox ui:field="someTextBox" addStyleNames="myTableInput"/>
</g:FlowPanel>
<g:Button ui:field="someButton" text="Button" addStyleNames="myTableButton"/>
</g:FlowPanel>
</g:FlowPanel>
CSS :
.myTable {
display: table;
width: 100%;
}
.myTableRow {
display: table-row;
}
.myTableLabel {
display: table-cell;
}
.myTableCell {
display: table-cell;
width: 100%;
}
.myTableInput {
width: 100%;
}
.myTableButton {
display: table-cell;
}

Gwt UIBinder DockLauout north element raise error as must contain a widget, but found <app:HeaderPanel ui:field='headerPanel'>

While trying to use Gwt UIBinder to have a custom widget loaded from main UI i am getting exception as
[ERROR] <g:north size='5'> must contain a widget, but found <app:HeaderPanel ui:field='headerPanel'> Element <g:DockLayoutPanel styleName='{style.outer}' unit='EM'> (:8)
while parsing XML in development mode. Below is the XML which I created for the same
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:app='urn.import:com.test.test.client'
xmlns:test='urn.import=com.test.test.client'>
<ui:style src="Resources/GlobalStyles.css" />
<g:DockLayoutPanel unit='EM' styleName='{style.outer}'>
<g:north size='5'>
<app:HeaderPanel ui:field='headerPanel' />
</g:north>
<g:west size='14'>
<test:FriendList ui:field='friendList' />
</g:west>
<g:center>
<g:HTMLPanel styleName='{style.boxPadding}'>
<div class="{style.titleBar}">Latest Activity</div>
<g:ScrollPanel ui:field='mainPanel' styleName='{style.mainPanel}' />
</g:HTMLPanel>
</g:center>
<g:south size="3">
<g:HTMLPanel styleName='{style.footerPanel}'>
<div>
Contact us
|
Privacy
|
About
</div>
</g:HTMLPanel>
</g:south>
</g:DockLayoutPanel>
</ui:UiBinder>
The headerPanel widget exits in the hierarchy. The corresponding code for above UiBinder is given below
public class TestApp implements EntryPoint {
#UiField
HeaderPanel headerPanel;
#UiField
ScrollPanel mainPanel;
RootLayoutPanel root;
private static TestApp singleton;
public static TestApp get() {
return singleton;
}
interface TestAppUiBinder extends UiBinder<DockLayoutPanel, TestApp> {
}
private static TestAppUiBinder uiBinder = GWT
.create(TestAppUiBinder.class);
#Override
public void onModuleLoad() {
// TODO Auto-generated method stub
singleton = this;
DockLayoutPanel outer = uiBinder.createAndBindUi(this);
root = RootLayoutPanel.get();
root.add(outer);
}
}
Basically I am novice in Gwt and trying to learn the things. Any pointer in this regard will be a great help.
Thanks.
What is
<app:HeaderPanel ui:field='headerPanel' />? If it does not extend Widget then it will not work. Try putting <g:Label>FOO</g:Label> in there and see if it works. Also make sure that your xmlns is correct. It will look for Header Panel in the package com.test.test.client. If you are trying to use the gwt Header Panel then it needs to be
<g:HeaderPanel ui:field="headerPanel" />
I think you are misunderstanding the xmlns. This tells gwt where to look for your java class. Both app and test are pointing to the same package. You should only add namespaces when you want to include your own custom widget classes or extra things like CellTable and DataGrid. I believe you are wanting to use the header.
Issue got fixed as it was xml parsing issue.
Thanks for providing inputs.

GWT - CssResource - common style - good practice

I have 5 views(.ui.xml). On every view i paste soemthing like that:
<ui:style src="../MyStyle.css" />
and on every button on every page I put styleName attribute:
<g:Button ui:field="buttonName" styleName="{style.myButtonStyle}" />
My Question is: Do I have to put styleName for all my buttons ? I would like to do something general style for this kind of widget .
What is good practice for this case?
Have you tried to customize GWT themes or create your own ? I think this is what you need to do.
Create your own button MyButton by extending Composite and define the UIBinder for this Button with style once.
Next you can re-use this button by adding your own namespace in the views.
Here's your widget :
package com.example.widgets;
...
public class MyButton extends Composite {
interface MyButtonUiBinder extends UiBinder<Widget, MyButton> {
}
private static MyButtonUiBinder uiBinder = GWT.create(MyButtonUiBinder.class);
#UiField
Button wrapped;
public MyButton() {
initWidget(uiBinder.createAndBindUi(this));
}
}
and the UIBinder file :
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:g='urn:import:com.google.gwt.user.client.ui'>
<ui:style>
.myStyle {
text-shadow: gray;
color: gray;
font-size: 12px;
text-decoration: italic;
}
</ui:style>
<g:HTMLPanel>
<g:Button ui:field="wrapped" styleName="{style.myStyle}" />
</g:HTMLPanel>
</ui:UiBinder>
In your views, you can now include this button in the UIBinder files :
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g='urn:import:com.google.gwt.user.client.ui' xmlns:k='urn:import:com.example.widgets'>
<g:AbsolutePanel width="350px" height="225px">
<g:at left='10' top='0'>
<k:MyButton></k:MyButton>
</g:at>
</g:AbsolutePanel>
</ui:UiBinder>
If you need to set the text or other properties on your personal widget, simply delegate the methods from the wrapped button to expose them.
One way would be to use addStyleDependentName() which would create an additional style by appending that to the primary style name, and allow you to apply specific styling.
For example, .gwt-Button is the default primary style for Button. If you have a set of 5 (N) buttons you like to style in the same way, you'd instantiate them with , which would add an additional style for this button: .gwt-Button-customButton, which you can add to a .css file and include in the module once.