Кнопка закрытия GWT в строке заголовка DialogBox - PullRequest
13 голосов
/ 29 мая 2009

Есть ли способ, не поддерживающий JSNI, добавить кнопку закрытия в область строки заголовка DialogBox?

Ответы [ 14 ]

16 голосов
/ 16 ноября 2009

Мы использовали GWT-ext с самого начала в нашем проекте. Это была плохая идея. У них много классных виджетов, но они не являются виджетами GWT И не имеют совместимости с виджетами GWT. После того, как вы выберете GWT-Ext, все, даже механизм событий, должно быть в GWT-Ext, а не в GWT. Эта библиотека не будет обновлена ​​для новейшей версии GWT, поскольку библиотека Ext для JavaScript больше не является бесплатной. Сейчас мы удаляем GWT-Ext из нашего проекта.

Невозможно добавить другой виджет в заголовок GWT DialogBox, но вы можете расширить «DecoratedPanel» (это родительский элемент DialogBox). Посмотрите на источник DialogBox, чтобы узнать методы, в частности, как он добавляет объект Caption на панель и как реализовано перетаскивание окна.

Вот что мы сделали здесь, и это работает очень хорошо. Мы создали наш собственный класс Caption, расширяющий FocusablePanel (SimplePanel, который фиксирует все события мыши), и добавили к нему HorizontalPanel с кнопками и текстом. Нам пришлось переопределить onAttach () и onDetach (), просто вызвав метод super (они защищены).

Я считаю, что мне не разрешено размещать здесь наш исходный код, поэтому я просто могу дать вам эти советы.

10 голосов
/ 15 марта 2010

Вы можете сделать это, добавив кнопку в центральную панель DialogBox:

Image closeButton = new Image("");
closeButton.addClickHandler(new ClickHandler() {
   public void onClick(ClickEvent event) {
      registerBox.hide();               
   }
});

closeButton.setStyleName("TopRight");

Затем поместите его с помощью CSS:

.TopRight {
   float:right;
   margin-top:-22px;
   width:16px;
   height:16px;
   display:block;
   background-image: url(images/cancel_16.png);
}
9 голосов
/ 01 ноября 2011

Я создал этот класс титров:

public class DialogBoxCaptionWithCancel extends Composite 
    implements Caption, HasClickHandlers {

@UiField
HTMLPanel mainPanel;
@UiField
HTML captionLabel;
@UiField
PushButton cancelButton;

private HandlerManager handlerManager = null;

private static final Binder binder = GWT.create(Binder.class);

interface Binder extends UiBinder<Widget, DialogBoxCaptionWithCancel> {
}

public DialogBoxCaptionWithCancel() {
    initWidget(binder.createAndBindUi(this));

    mainPanel.setStyleName("Caption");
    Image upImage = new Image("images/closeWindow.png");
    Image hoverImage = new Image("images/closeWindowFocus.png");
    cancelButton.getUpFace().setImage(upImage);
    cancelButton.getUpHoveringFace().setImage(hoverImage);
    cancelButton.setStylePrimaryName("none");
}

/*
 * (non-Javadoc)
 * 
 * @see com.google.gwt.user.client.ui.Widget#onLoad()
 */
@Override
protected void onLoad() {
    super.onLoad();

    handlerManager = new HandlerManager(this);
}

@UiHandler("cancelButton")
public void cancelButtonOnClick(ClickEvent event) {
    handlerManager.fireEvent(event);
}

@Override
public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
    return handlerManager.addHandler(MouseDownEvent.getType(), handler);
}

@Override
public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
    return handlerManager.addHandler(MouseUpEvent.getType(), handler);
}

@Override
public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
    return handlerManager.addHandler(MouseOutEvent.getType(), handler);
}

@Override
public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
    return handlerManager.addHandler(MouseOverEvent.getType(), handler);
}

@Override
public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
    return handlerManager.addHandler(MouseMoveEvent.getType(), handler);
}

@Override
public HandlerRegistration addMouseWheelHandler(MouseWheelHandler handler) {
    return handlerManager.addHandler(MouseWheelEvent.getType(), handler);
}

@Override
public String getHTML() {
    return "";
}

@Override
public void setHTML(String html) {
}

@Override
public String getText() {
    return this.captionLabel.getText();
}

@Override
public void setText(String text) {
    this.captionLabel.setText(text);
}

@Override
public void setHTML(SafeHtml html) {
}

@Override
public HandlerRegistration addClickHandler(ClickHandler handler) {
    return handlerManager.addHandler(ClickEvent.getType(), handler);
}

}

Изображения просто захватываются из поведения IE8 при наведении курсора на кнопку отмены.

Вот код UiBinder:

<!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'>

<ui:style>
    .htmlField {
        width: 100%;
    }

    .pushButton {
        border: none;
        padding: 0px;
        width: 49px;
        height: 21px;
    }
</ui:style>

<g:HTMLPanel ui:field="mainPanel">
    <table border="0" cellpadding="0" cellspacing="0" width="100%">
        <tr>
            <td width="100%">
                <g:HTML ui:field="captionLabel" addStyleNames="{style.htmlField}"></g:HTML>
            </td>
            <td>
                <g:PushButton ui:field="cancelButton" addStyleNames="{style.pushButton}"></g:PushButton>
            </td>
        </tr>
    </table>
</g:HTMLPanel>
</ui:UiBinder>

Тогда мой класс, который расширяет DialogBox, имеет следующее:

public class MyDialogBox extends DialogBox implements ClickHandler {
...
// instantiate the caption with the cancel button
private static DialogBoxCaptionWithCancel caption = new DialogBoxCaptionWithCancel();
...
 public MyDialogBox() {
    // construct the dialog box with the custom caption
    super(false, false, caption);

    setWidget(binder.createAndBindUi(this));

    // set the caption's text
    caption.setText("My Caption");
}
....
protected void onLoad() {
    super.onLoad();

    // let us react to the captions cancel button
    caption.addClickHandler(this);
}
...
@Override
public void onClick(ClickEvent event) {
    // the caption's cancel button was clicked
    this.hide();
}
5 голосов
/ 04 июня 2009

Более простым решением является использование gwt-ext (http://code.google.com/p/gwt-ext/).. Оно бесплатное, простое в использовании и интеграции. Вы можете увидеть их витрину http://www.gwt -ext.com / demo / . Я думаю, что вы хотите, чтобы MessageBox или Layout Window (они находятся в категории витрины Windows).

С уважением.

3 голосов
/ 29 июня 2011

Вы можете попробовать это, слегка улучшенное решение от fungus1487:

import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.HasDirection;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.*;

/**
 * @author Andrey Talnikov
 */
public class ClosablePopup extends DialogBox {

    private Anchor closeAnchor;

    /**
     * Instantiates new closable popup.
     *
     * @param title        the title
     * @param defaultClose it {@code true}, hide popup on 'x' click
     */
    public ClosablePopup(String title, boolean defaultClose) {
        super(true);

        closeAnchor = new Anchor("x");

        FlexTable captionLayoutTable = new FlexTable();
        captionLayoutTable.setWidth("100%");
        captionLayoutTable.setText(0, 0, title);
        captionLayoutTable.setWidget(0, 1, closeAnchor);
        captionLayoutTable.getCellFormatter().setHorizontalAlignment(0, 1,
                HasHorizontalAlignment.HorizontalAlignmentConstant.endOf(HasDirection.Direction.LTR));

        HTML caption = (HTML) getCaption();
        caption.getElement().appendChild(captionLayoutTable.getElement());

        caption.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                EventTarget target = event.getNativeEvent().getEventTarget();
                Element targetElement = (Element) target.cast();

                if (targetElement == closeAnchor.getElement()) {
                    closeAnchor.fireEvent(event);
                }
            }
        });

        if (defaultClose) {
            addCloseHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    hide();
                }
            });
        }
    }

    public void addCloseHandler(ClickHandler handler) {
        closeAnchor.addClickHandler(handler);
    }
}
2 голосов
/ 30 июня 2012

Полагаю, простой ответ на этот вопрос заключается в создании экземпляра виджета для замены стандартного виджета «Заголовок» из DialogBox. Я создал подпись с кнопкой справа, и вы можете выбрать ссылку на нее. Затем вы можете добавить любое событие клика по вашему желанию.

В GWT 2.4 я использовал следующее решение:

import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.DialogBox.Caption;

/**
 * @author Cristiano Sumariva
 */
public class ButtonCaption extends HorizontalPanel implements Caption
{
  protected InlineLabel text;
  protected PushButton closeDialog;

  /**
   * @return the button at caption
   */
  public PushButton getCloseButton()
  {
    return closeDialog;
  }
  public ButtonCaption( String label )
  {
    super();
    setWidth( "100%" );
    setStyleName( "Caption" ); // so you have same styling as standard caption widget
    closeDialog = new PushButton();
    add( text = new InlineLabel( label ) );
    add( closeDialog );
    setCellWidth( closeDialog, "1px" ); // to make button cell minimal enough to it
  }
  /* (non-Javadoc)
   * @see com.google.gwt.event.dom.client.HasMouseDownHandlers#addMouseDownHandler(com.google.gwt.event.dom.client.MouseDownHandler)
   */
  @Override
  public HandlerRegistration addMouseDownHandler( MouseDownHandler handler )
  {
    return addMouseDownHandler( handler );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.event.dom.client.HasMouseUpHandlers#addMouseUpHandler(com.google.gwt.event.dom.client.MouseUpHandler)
   */
  @Override
  public HandlerRegistration addMouseUpHandler( MouseUpHandler handler )
  {
    return addMouseUpHandler( handler );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.event.dom.client.HasMouseOutHandlers#addMouseOutHandler(com.google.gwt.event.dom.client.MouseOutHandler)
   */
  @Override
  public HandlerRegistration addMouseOutHandler( MouseOutHandler handler )
  {
    return addMouseOutHandler( handler );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.event.dom.client.HasMouseOverHandlers#addMouseOverHandler(com.google.gwt.event.dom.client.MouseOverHandler)
   */
  @Override
  public HandlerRegistration addMouseOverHandler( MouseOverHandler handler )
  {
    return addMouseOverHandler( handler );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.event.dom.client.HasMouseMoveHandlers#addMouseMoveHandler(com.google.gwt.event.dom.client.MouseMoveHandler)
   */
  @Override
  public HandlerRegistration addMouseMoveHandler( MouseMoveHandler handler )
  {
    return addMouseMoveHandler( handler );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.event.dom.client.HasMouseWheelHandlers#addMouseWheelHandler(com.google.gwt.event.dom.client.MouseWheelHandler)
   */
  @Override
  public HandlerRegistration addMouseWheelHandler( MouseWheelHandler handler )
  {
    return addMouseWheelHandler( handler );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.user.client.ui.HasHTML#getHTML()
   */
  @Override
  public String getHTML()
  {
    return getElement().getInnerHTML();
  }

  /* (non-Javadoc)
   * @see com.google.gwt.user.client.ui.HasHTML#setHTML(java.lang.String)
   */
  @Override
  public void setHTML( String html )
  {
    remove( text );
    insert( text, 1 );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.user.client.ui.HasText#getText()
   */
  @Override
  public String getText()
  {
    return text.getText();
  }

  /* (non-Javadoc)
   * @see com.google.gwt.user.client.ui.HasText#setText(java.lang.String)
   */
  @Override
  public void setText( String text )
  {
    this.text.setText( text );
  }

  /* (non-Javadoc)
   * @see com.google.gwt.safehtml.client.HasSafeHtml#setHTML(com.google.gwt.safehtml.shared.SafeHtml)
   */
  @Override
  public void setHTML( SafeHtml html )
  {
    setHTML( html.asString() );
  }
}

Расширяет DialogBox для использования нового доступного ButtonCaption

class CaptionCloseableDialogBox extends DialogBox
{
  public CaptionCloseableDialogBox()
  {
    super( new ButtonCaption( "dialog box title" ) );
    setAutoHideEnabled( false );

    ButtonCaption ref = (ButtonCaption) this.getCaption();
    PushButton closeButton = ref.getCloseButton();
    // apply button face here closeButton;
    closeButton.addClickHandler( /* attach any click handler here like close this dialog */ );
  }
}

Надеюсь, это поможет любому.

2 голосов
/ 01 июня 2009

Да, есть

Нет, нет - по крайней мере, без работы с самим классом GWT DialogBox или путем воссоздания DialogBox с использованием общих виджетов. Это известная проблема в GWT, также известная как 1405 (пометьте ее, чтобы показать свой интерес).

Тем не менее, DialogBox не дает нам инструментов для этого, поэтому нам нужно расширить его - Редактировать: это не работает.

Если вы хотите сделать вставную замену для DialogBox, вы можете назвать свой класс DialogBox и импортировать его вместо того, который включен в GWT. Эта ветка на форуме GWT дает более подробную информацию о том, как это можно сделать (устарела, использует слушателей) Устаревшая внутренняя часть DialogBox сильно изменилась с этой ветки - она ​​не не работает.

Вот некоторый код, который я взломал, чтобы получить те же результаты (использовал связанный поток для руководства) . Это не работает:

MyDialogBox:

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

public class MyDialogBox extends DialogBox {

    private class crossHandler implements ClickHandler, MouseOverHandler, MouseOutHandler
    {

        @Override
        public void onClick(ClickEvent event) {
            hide();
            Window.alert("Click!");
        }

        @Override
        public void onMouseOver(MouseOverEvent event) {
            DOM.setStyleAttribute(cross.getElement(), "font-weight", "bold");

        }

        @Override
        public void onMouseOut(MouseOutEvent event) {
            DOM.setStyleAttribute(cross.getElement(), "font-weight", "normal");

        }


    }

    Label cross = new Label("X"); // The close button
    crossHandler crosshandler = new crossHandler();
    HTML caption = new HTML(); // The caption aka title
    HorizontalPanel captionPanel = new HorizontalPanel(); // Contains caption and cross


      /**
       * Creates an empty dialog box. It should not be shown until its child widget
       * has been added using {@link #add(Widget)}.
       */
    public MyDialogBox()
    {
        this(false);
    }

  /**
   * Creates an empty dialog box specifying its "auto-hide" property. It should
   * not be shown until its child widget has been added using
   * {@link #add(Widget)}.
   * 
   * @param autoHide <code>true</code> if the dialog should be automatically
   *          hidden when the user clicks outside of it
   */
    public MyDialogBox(boolean autoHide) {
            this(autoHide, true);
          }

    /**
     * Creates an empty dialog box specifying its "auto-hide" property. It should
     * not be shown until its child widget has been added using
     * {@link #add(Widget)}.
     * 
     * @param autoHide <code>true</code> if the dialog should be automatically
     *          hidden when the user clicks outside of it
     * @param modal <code>true</code> if keyboard and mouse events for widgets not
     *          contained by the dialog should be ignored
     */
    public MyDialogBox(boolean autoHide, boolean modal)
    {
        super(autoHide, modal);

        cross.addClickHandler(crosshandler); 
        cross.addMouseOutHandler(crosshandler);
        cross.addMouseOverHandler(crosshandler);

        captionPanel.add(caption);
        captionPanel.add(cross);
        captionPanel.setStyleName("caption");

        Element td = getCellElement(0, 1);  // Get the cell element that holds the caption
        td.setInnerHTML(""); // Remove the old caption
        td.appendChild(captionPanel.getElement());



    }

    @Override
    public void setText(String text)
    {
        caption.setText(text);
    }

    public String getText()
    {
        return caption.getText();
    } 

    public void setHtml(String html)
    {
        caption.setHTML(html);
    }

    public String getHtml()
    {
        return caption.getHTML();
    }

Примечание: Этот код не работает. ClickEvent не отправляется из cross, а вместо этого из MyDialogBox, независимо от того, добавляете ли вы ClickHandlers в cross или нет, IOW MyDialogBox является отправителем / источником, и поэтому невозможно проверить на cross. При нажатии на крестик по некоторым причинам не срабатывает ClickEvent.

Edit: Похоже, что это не может быть сделано без хаков, если вы не напишите свой собственный DialogBox (почти) с нуля или исправите проблему 1405. Конечно, есть ряд существующих библиотек, которые уже решили эту проблему, то есть SmartGWT и GWT-Ext , но их реализация в основном производится с нуля.

Итак, чтобы ответить на ваш вопрос в одном предложении: Да, есть способ, но он вам не понравится:)

1 голос
/ 05 марта 2012

Это работает, если вы просто не хотите простое решение для поставленного вопроса:

    Image button = new Image("images/cancel.png"); 

    button.addClickHandler(new ClickHandler(){ 
        public void onClick(ClickEvent event) { 
            hide();
        }
    }); 
    button.setStyleName("dialog-close");

    HorizontalPanel header = new HorizontalPanel();
    header.add(new HTML("Example Tool"));
    header.add(button);

    setHTML(header.getElement().getInnerHTML());
1 голос
/ 13 мая 2011

Я понимаю, что это смехотворно старо, но вы можете просто использовать абсолютное позиционирование с верхним и правым 0, чтобы получить виджет в верхнем правом углу. Диалоговое окно само по себе абсолютно позиционировано, поэтому позиционирование вашего виджета будет против него.

1 голос
/ 27 февраля 2011

Просто используя GWT и не используя внешние библиотеки, вы можете перехватывать события щелчка на элементе заголовка и выполнять проверку нажатия, чтобы определить, находится ли координата мыши x, y в пределах элемента привязки (или другого элемента, который вы используете в ClickHandler).

// Create anchor we want to accept click events
final Anchor myAnchor = new Anchor("My Anchor");

// Add handler to anchor
myAnchor.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    Window.alert("Anchor was clicked");
  }
});

// Create dialog
final DialogBox myDialog = new DialogBox();
myDialog.setText("My Dialog");

// Get caption element
final HTML caption = ((HTML)myDialog.getCaption());

// Add anchor to caption
caption.getElement().appendChild(myAnchor.getElement());

// Add click handler to caption
caption.addClickHandler(new ClickHandler() {
  @Override
  public void onClick(ClickEvent event) {
    // Get x,y caption click relative to the anchor
    final int x = event.getRelativeX(myAnchor.getElement());
    final int y = event.getRelativeY(myAnchor.getElement());

    // Check click was within bounds of anchor
    if(x >= 0 && y >= 0 && 
      x <= myAnchor.getOffsetWidth() && 
      y <= myAnchor.getOffsetHeight()) {
        // Raise event on anchor
        myAnchor.fireEvent(event);
    }
  }
});

// Show the dialog
myDialog.show();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...