Adding style and removing style to a widget in gwt - gwt

I wrote a widget like this:
public class GroupLbl extends Composite implements ClickHandler, MouseOutHandler {
private Label lbl;
private GroupLblHandler lblHandler = null;
private HorizontalPanel hp;
public void onClick(ClickEvent event) {
hp.setStyleName("background-GroupLbl");
if (event.getSource().equals(folder) || event.getSource().equals(lbl)) {
lblHandler.onGroupLabelSelect(this);
}
}
public GroupLbl(String title, GroupLblHandler handler) {
hp.add(lbl);
lblHandler = handler;
if (handler != null) {
lbl.addClickHandler(this);
}
initWidget(hp);
}
#Override
public Widget getWidget() {
return hp;
}
public void onMouseOut(MouseOutEvent event) {
hp.removeStyleName("background-GroupLbl");
}
}
I use this widget in my form,when the user click on one of INSTANCE of widget the stylename should be assign to this and when the user click on other the stylename should assign to that and the first shoud remove the style name I implemented mouseouthandler but it doese not work,the style set the bgcolor to hp so the user understand which grouplbl he/she has selected.what shoul I do(It is part of my code)? tnx and excuse me for my bad english !!!

Define an additional CSS style with suffix -background with the bg color you wish to have.
Instead of setStyleName use addStyleDependentName( "background" ) along with removeStyleDependentName( "background" ) to add/remove -background style.

Related

change moved widget on drop with gwt-dnd 3.3.0

situation
I'm writing a admintool to change a GWT based GUI via Browser.
I want the Admin to use drag and drop to create and change the GUI.
To realize the dnd I use gwt-dnd 3.3.0
I have a toolbar in my admintool, from which I can drag the different objects.
Every object in the toolbar is a plain HTML widget with text inside.
I would like to change the Widget when it is droped.It should change from the HTML widget to the original widget I like to use.
problem & tried solution
At the moment I can change the widget on Drop, then it throws an exception and the "moving widget" don't get removed from the page. The "moving widget" is still dragable and shows the "move designe"
I think this happens, because the Drag or Drophandler do not know the moving widget, because i changed the drop widget...
Here is the code:
dragController.addDragHandler(new DragHandler(){
public void onDragEnd(DragEndEvent event) {
...
}
public void onDragStart(DragStartEvent event) {
...
}
public void onPreviewDragEnd(DragEndEvent event)
throws VetoDragException {
final DragContext mycontent = event.getContext();
List<Widget> mywl = mycontent.selectedWidgets;
for(int i = 0; i < mywl.size(); i++)
{
String stemp = ((HTML)mywl.get(i)).getText();
if(stemp.contains("Container")&&!stemp.contains("SubContainer"))
{
FlowPanel mypanel = new FlowPanel();
HTML htmltemp = new HTML("Label");
htmltemp.setStyleName("edit-dndcontainer");
mypanel.add(htmltemp);
mypanel.setStyleName("edit-dndcontainer");
mywl.add(i, mypanel);
dragController.makeDraggable(mypanel);
mywl.get(i).removeFromParent();
mywl.remove(i+1);
mycontent.selectedWidgets = mywl;
}
else if(stemp.contains("Label"))
{
...
}
else
{
...
throw new VetoDragException();
}
}
}
public void onPreviewDragStart(DragStartEvent event)
throws VetoDragException
{
...
}
});
question
Is gwt-dnd the correct lib to use for this behaviour, or should I use native dnd of GWT?
How can I change the dnd-widget on drop with gwt-dnd?
Thanks for your help
My approach was not that bad, but instead of working with the DragContext, I have to work with the getSelectedWidgets().iterator() from the DragController.
edit
I switched my code to onDragEnd(), in this case I don't screw up the moving widget. And I changed the Draggable widget to a Panel. I just have to add and remove widgets from it.
answer
Samplecode:
dragController.addDragHandler(new DragHandler(){
public void onDragEnd(DragEndEvent event) {
Iterable<Widget> myiterable = myDragCTRL_subcont.getSelectedWidgets();
Widget mywidget = myiterable.iterator().next();
FlowPanel flowtemp = ((FlowPanel)mywidget);
flowtemp.add(new HTML("label"));
...
...
}
public void onDragStart(DragStartEvent event) {
...
}
public void onPreviewDragEnd(DragEndEvent event)
throws VetoDragException {
...
}
public void onPreviewDragStart(DragStartEvent event)
throws VetoDragException {
...
}
});

GWT CellTable tooltip not working properly

I am using a CellTable and I want to show a tooltip whenever I hover over any of the cell.
My code is working fine but the tooltip is not changing its position.
What I mean to say is, if I hover over cell 1 tooltip shows and then if I hover over cell 100, the tooltip data changes but the tooltip still shows at cell 1.
I am using following code:
cellTable.addCellPreviewHandler(new Handler<List<String>>() {
#Override
public void onCellPreview(CellPreviewEvent<List<String>> event) {
if ("mouseover".equals(event.getNativeEvent().getType())) {
Element cellElement = event.getNativeEvent().getEventTarget().cast();
cellElement.setTitle('cell contents go here.');
}
}
}
Any help is much appreciated.
Thanks.
You can extend Column class and override method render. In render method you can use property "title", which is used to set the tool tip text. Simple example:
SampleColumn<T> extends TextColumn<T> {
#Override
public void render(Context context, T object, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<div title=\"" + getTitle(object) + "\">");
sb.appendEscaped(getValue(object));
sb.appendHtmlConstant("</div>");
}
#Override
public String getValue(T object) {
return displayedValue;
}
public String getTitle(T object) {
return yourTooltipText;
}
}
When using this code, the tooltip will be exacly near the target cell.
if (cellElement.getParentElement()
.getFirstChildElement().isOrHasChild(Element.as(event.getNativeEvent().getEventTarget()))
&& cellElement.getTagName().equalsIgnoreCase("span"))
This resolves the issue.
Thanks Andrei & Alex for replies.
Thank you all, I was looking for a solution to that as well.
Using A cup of tea's answer, I made a generic class that can be reused to add tooltips to any cell. It's based on a decorator pattern. Here it is if it may help someone:
public class TooltipCell extends AbstractSafeHtmlCell<String>
{
AbstractCell<String> cell;
private String tooltip;
public TooltipCell(AbstractCell<String> cell, String tooltip)
{
super(SimpleSafeHtmlRenderer.getInstance(), BrowserEvents.CLICK, BrowserEvents.KEYDOWN);
this.cell = cell;
this.tooltip = tooltip;
}
#Override
protected void render(com.google.gwt.cell.client.Cell.Context context, SafeHtml data, SafeHtmlBuilder sb)
{
sb.appendHtmlConstant("<div title=\"" + tooltip + "\">");
cell.render(context, data.asString(), sb);
sb.appendHtmlConstant("</div>");
}
#Override
public void onBrowserEvent(com.google.gwt.cell.client.Cell.Context context, Element parent, String value, NativeEvent event, ValueUpdater<String> valueUpdater)
{
cell.onBrowserEvent(context, parent, value, event, valueUpdater);
}
}
Then it can be used as follows:
myColumn = new Column<MyObject, String>(new TooltipCell(new ButtonCell(), "tooltip text"))
{
#Override
public String getValue(CurrencyDTO object)
{
return "button text";
}
};
This solution works:
cellTable.addCellPreviewHandler(new Handler<List<String>>() {
#Override
public void onCellPreview(CellPreviewEvent<List<String>> event) {
if ("mouseover".equals(event.getNativeEvent().getType())) {
cellTable.getRowElement(event.getIndex()).getCells().getItem(event.getColumn()).setTitle('cell contents go here.');
}
}
}
cellTable.addCellPreviewHandler(new Handler<List<String>>() {
#Override
public void onCellPreview(CellPreviewEvent<List<String>> event) {
if ("mouseover".equals(event.getNativeEvent().getType())) {
cellTable.getRowElement(event.getIndex()).getCells().getItem(event.getColumn()).setTitle('cell contents go here.');
}
}
}
Andrei's solution works good but there is a bug should be fixed:
cellTable.getRowElement(event.getIndex() - cellTable.getPageStart()).getCells().getItem(event.getColumn()).setTitle('cell contents go here.');

Getting header column names in Cell table on click in GWT

I am using Cell Table of GWT 2.2 version. I want to get the name of the header column on which I have clicked. I didn't get any click event on the same.
Is there any work around by which I can accomplish my task.
Something like this? ;)
public class CellTableExample implements EntryPoint, ClickHandler {
private static class SomeEntity {
/* ... */
}
private static class ClickableTextHeader extends TextHeader {
private ClickHandler handler;
public ClickableTextHeader(String text, ClickHandler handler) {
super(text);
this.handler = handler;
}
#Override
public void onBrowserEvent(Context context, final Element elem,
final NativeEvent event) {
//maybe hijack click event
if(handler != null) {
if(Event.ONCLICK == Event.getTypeInt(event.getType())) {
handler.onClick(new ClickEvent() {
{
setNativeEvent(event);
setRelativeElement(elem);
setSource(ClickableTextHeader.this);
}
});
}
}
//default dom event handler
super.onBrowserEvent(context, elem, event);
}
}
CellTable<SomeEntity> cellTable;
TextColumn<SomeEntity> firstColumn;
TextColumn<SomeEntity> secondColumn;
TextColumn<SomeEntity> thirdColumn;
#Override
public void onModuleLoad() {
/* somehow init columns - it's not the point for this example */
cellTable.addColumn(firstColumn, new ClickableTextHeader("First column header", this));
cellTable.addColumn(secondColumn, new ClickableTextHeader("Second column header", this));
cellTable.addColumn(thirdColumn, new ClickableTextHeader("Third column header", this));
}
#Override
public void onClick(ClickEvent event) {
ClickableTextHeader source = (ClickableTextHeader) event.getSource();
Window.alert(source.getValue());
}
}
Hijacking event could look simpler if we used "simple listener interface" - i just wanted to be "semanticaly compliant with out-of-the-box Handlers" :)

GWT - How to associate a business object to a widget

I'd like a way to easily tie a widget back to the business object it is rendering. So when the user interacts with a widget I can easily determine the business object holding the data for that widget.
For example, if we imagine a calendar widget that we're going to implement with an AbsolutePanel. For each appt object we'll add a label to the calendar. Then when a user clicks on a label he can update the appt. So I need to know which appt object that label refers to.
For instance, if we look at the following code; if the label for an appointment receives a click, how can I find out to which appt it represented ? The only solution I can see is to create a ApptLabel sub-class for Label which would hold a reference to its appt. This is fine, but the example illustrates a more general need which is to associate widgets with data objects; however this would mean that every object that has a presence in a view needs to subclass a widget. that seems heavy - I expected to find something in the framework e.g. a string property in a widget that I can set to an object key
other approaches I tried; maintaining a map of Map -- this didnt work as the label object I create doesnt appear to be the same (in terms of the Object.equals which I guess is what HashMap uses)
class WidgetCalendar extends Composite {
AbsolutePanel m_panel = new AbsolutePanel();
m_panel.setStylePrimaryName("calendar");
m_panel.setPixelSize(width, height);
public WidgetCalendar(ArrayList<BomAppt> appts) {
initWidget(m_panel);
for (BomAppt a : appts) {
Label l = new Label();
l.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// how do I know my BomAppt in here ?
}
m_panel.add(l, someX, someY);
}
}
}
Ideally I can do something like this
class WidgetCalendar extends Composite {
AbsolutePanel m_panel = new AbsolutePanel();
m_panel.setStylePrimaryName("calendar");
m_panel.setPixelSize(width, height);
public WidgetCalendar(ArrayList<BomAppt> appts) {
initWidget(m_panel);
for (BomAppt a : appts) {
Label l = new Label();
l.setItemData(a.getUniqueId());
l.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
BomAppt a = BomAppt.getApptWithId(e.getItemData())
}
}
m_panel.add(l, someX, someY);
}
}
}
This is the solution where I create a subclass, this seems heavy to me and I'd prefer something simpler
class ApptLabel extends Label {
public ApptLabel(BomAppt a) {
m_a = a;
this.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
m_a.doSomething();
});
}
BomAppt m_a;
}
class WidgetCalendar extends Composite {
AbsolutePanel m_panel = new AbsolutePanel();
m_panel.setStylePrimaryName("calendar");
m_panel.setPixelSize(width, height);
public WidgetCalendar(ArrayList<BomAppt> appts) {
initWidget(m_panel);
for (BomAppt a : appts) {
BomLabel l = new BomLabel();
l.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// how do I know my BomAppt in here ?
}
m_panel.add(l, someX, someY);
}
}
}
For instance, if we look at the following code; if the label for an
appointment receives a click, how can I find out to which appt it
represented ?
By using Composite pattern you can find out which widget was clicked, initially you should create your own custom Appointment widget which is responsible for drawing one appointment. And in you Appointment widget you can have a set of other widgets, in your case, for Label add click handler. Once user clicks that label, you can execute business logic with its data and you can represent data.
public class Appointment extends Composite {
private AppointmentDetails data;
public Appointment(AppointmentDetails data){
draw(data);
}
private void draw(AppointmentDetails data){
Label label = new Label();
label.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// do your business logic with this AppointmentDetails
}
});
}
}
After that you should have one Calendar widget which contains several Appointments.
Keep in your mind: your classes each serve a single, very clearly defined purpose, separated from other classes with other clearly defined purposes.

gwt:adding clickhandler to ImageResource cell

I want to add an image to my celltable , for that i use imageResouce as below
interface Resources extends ClientBundle {
#Source("close.png")
ImageResource getImageResource();
}
Resources resources = GWT.create(Resources.class);
deleteJobColumn = new Column<EmployerJobs, ImageResource>(new ImageResourceCell()) {
#Override
public ImageResource getValue(EmployerJobs object) {
return resources.getImageResource();
}
};
Its working perfectly fine , i am getting image in my celltable but Now i want to add clickhandler to that image ,For that i am using field Updater like below
display.getListJobsWidget().getDeleteJobColumn().setFieldUpdater(
new FieldUpdater<EmployerJobs, ImageResource>() {
public void update(int index, EmployerJobs employerJobs,
ImageResource value) {
Window.alert("Hello");
}
});
so now when i click on that above image cell it should say "Hello", but its not doing any thing .. Any solution ..
Thanks
ImageResourceCell doesn't have any wiring to call the ValueUpdater, it is just designed to draw the image and be done with it.
You have a few ways you can change this:
Subclass ImageResourceCell and override onBrowserEvent - take a look at ButtonCell to see how this can work
Use a different cell class instead, like ActionCell - this doesn't take any data from the client, but will let you pass in a delegate isntead, which will be run when the thing is clicked. Use the ActionCell(SafeHtml,Delegate<C>) constructor to pass in your image, in the form of html
Build a new cell, subclassing AbstractCell, borrowing the render code from ImageResourceCell and the event code from ButtonCell or ActionCell to keep your code as generic and reusable as possible.
An example for the first solution provided by Colin. I found it a bit tricky to override getConsumedEvents but seems to work well.
public class ClickableImageResourceCell extends ImageResourceCell{
public ClickableImageResourceCell(){
super();
}
#Override
public Set<String> getConsumedEvents() {
Set<String> set = new HashSet<String>();
set.add("click");
return set;
}
#Override
public void onBrowserEvent(com.google.gwt.cell.client.Cell.Context context, Element parent, ImageResource value, NativeEvent event, ValueUpdater<ImageResource> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
if ("click".equals(event.getType())) {
EventTarget eventTarget = event.getEventTarget();
if (!Element.is(eventTarget)) {
return;
}
if (parent.getFirstChildElement().isOrHasChild(Element.as(eventTarget))) {
// Ignore clicks that occur outside of the main element.
keyDown(context, parent, value, event, valueUpdater);
}
}
}
protected void keyDown(Context context, Element parent, ImageResource value,
NativeEvent event, ValueUpdater<ImageResource> valueUpdater) {
if (valueUpdater != null) {
valueUpdater.update(value);
}
}
}