How can I open the Bootstrap Dropdown programmatically? - gwt

I develop the GWT application. Also I use Twitter Bootstrap library and GWTQuery. There is the DropdownButton. I want to open it programmatically.
ui.xml like this:
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:g='urn:import:com.google.gwt.user.client.ui'
...
<b:DropdownButton text="Test" ui:field="dropdownButton">
<g:FlowPanel ui:field="contentPanel"/>
</b:DropdownButton>
I can open it via inspector of Google Chrome - add 'open' class to 'btn-group'. But it is impossible programmatically. I don't know why. Usages of addClassName / addStyleName methods are ignored.
Also I have tried to simulate click event via Document.get().createClickEvent, but the dropdown hasn't handlerManager. I have tried to call trigger and click with help of JQuery/GWTQuery.
Is it possible to open Dropdown programmatically?

You can try subclassing DropDownButton, adding a getter for the trigger button (at the end of the class), like this:
public class CustomDropdownButton extends DropdownBase {
private Button trigger;
/**
* Creates a DropdownButton without a caption.
*/
public CustomDropdownButton() {
super("div");
addStyleName("btn-group");
}
/**
* Creates a DropdownButton with the given caption.
*
* #param caption
* the button's caption
*/
public CustomDropdownButton(String caption) {
this();
setText(caption);
}
/**
* {#inheritDoc}
*/
#Override
protected IconAnchor createTrigger() {
trigger = new Button();
trigger.setCaret(true);
return trigger;
}
/**
* Sets the button's size.
*
* #param size
* the button's size
*/
public void setSize(ButtonSize size) {
trigger.setSize(size);
}
/**
* Sets the button's type.
*
* #param type
* the button's type
*/
public void setType(ButtonType type) {
trigger.setType(type);
}
/**
* Sets the button's icon.
*
* #param type
* the icon's type
*/
#Override
public void setIcon(IconType type) {
setBaseIcon(type);
}
/**
* {#inheritDoc}
*/
#Override
public void setBaseIcon(BaseIconType type) {
trigger.setBaseIcon(type);
}
#Override
public HandlerRegistration addClickHandler(ClickHandler handler) {
return trigger.addClickHandler(handler);
}
/**
* {#inheritDoc}
*/
#Override
public void setIconSize(IconSize size) {
trigger.setIconSize(size);
}
/**
* {#inheritDoc}
*/
#Override
public void setCustomIconStyle(String customIconStyle) {
trigger.setCustomIconStyle(customIconStyle);
}
/**
* {#inheritDoc}
*/
#Override
public void setIconPosition(IconPosition position) {
trigger.setIconPosition(position);
}
public Button getButton(){
return trigger;
}
}
Now you will have in your uiBinder xml :
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:g='urn:import:com.google.gwt.user.client.ui'
xmlns:c='urn:import:com.example.packageWithCustomDropDown'
...
<c:CustomDropdownButton text="Test" ui:field="dropdownButton">
<g:FlowPanel ui:field="contentPanel"/>
</b:CustomDropdownButton>
And now you can call, the click function, on the button : dropDownButton.getButton().click();
I don't test it, but it should work.
Hope it helps. :)

Related

Laravel Backpack basic request validation

I'm having an issue that I thought would be VERY simple to accomplish. I can not get this very basic request validation to work. I can enter "Bob" on the create form and the edit form and get no error messages. It simply inserts into the database.
Here's my code. I feel I'm doing/not doing something stupid.
UserCrudController.php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\UserRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
/**
* Class UserCrudController
* #package App\Http\Controllers\Admin
* #property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class UserCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* #return void
*/
public function setup()
{
CRUD::setModel(\App\Models\User::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/user');
CRUD::setEntityNameStrings('user', 'users');
}
/**
* Define what happens when the List operation is loaded.
*
* #see https://backpackforlaravel.com/docs/crud-operation-list-entries
* #return void
*/
protected function setupListOperation()
{
CRUD::column('name');
CRUD::column('email');
//CRUD::column('password');
/**
* Columns can be defined using the fluent syntax or array syntax:
* - CRUD::column('price')->type('number');
* - CRUD::addColumn(['name' => 'price', 'type' => 'number']);
*/
}
/**
* Define what happens when the Create operation is loaded.
*
* #see https://backpackforlaravel.com/docs/crud-operation-create
* #return void
*/
protected function setupCreateOperation()
{
CRUD::setValidation(UserRequest::class);
CRUD::field('name');
CRUD::field('email');
//CRUD::field('password');
/**
* Fields can be defined using the fluent syntax or array syntax:
* - CRUD::field('price')->type('number');
* - CRUD::addField(['name' => 'price', 'type' => 'number']));
*/
}
/**
* Define what happens when the Update operation is loaded.
*
* #see https://backpackforlaravel.com/docs/crud-operation-update
* #return void
*/
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}
UserRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => ['required','min:5','max:255'],
];
}
/**
* Get the validation attributes that apply to the request.
*
* #return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* #return array
*/
public function messages()
{
return [
//
];
}
}
I think what is happening is that you are not loading that controller.
If you have installed PermissionManager and now want to configure the UserCrudController you need to either manually register the routes yourself and point to your new controller, or alternativelly (and probably recommended) bind your new controller to the package one so your controller gets "served" instead of the package controller.
// In AppServiceProvider.php or any other provider of your choice:
$this->app->bind(
\Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class,
\App\Http\Controllers\Admin\UserCrudController::class
);
If you don't need to change everything in the Controller you can directly extend the package UserCrudController and only change the things you need.
<?php
namespace App\Http\Controllers\Admin;
class UserCrudController extends \Backpack\PermissionManager\app\Http\Controllers\UserCrudController
{
}
The package controller already extends the CrudController.
The validation is added on setupCreateOperation() that you can override to fit your needs.
Cheers

How to update decorator on file save?

I have created a plugin with decorator which takes current file as input and show appropriate decorator.
This is working fine and decorator is shown properly when the eclipse loads for the first time.
However, when file changes, decorator is not updated.
How can I update decorator every time file is modified? i.e. How can I update decorator on file save event?
This is the sample code
public class Decorator implements ILightweightLabelDecorator {
private final ImageDescriptor OVERLAY1 = AbstractUIPlugin.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/1.png");
private final ImageDescriptor OVERLAY2 = AbstractUIPlugin.imageDescriptorFromPlugin(Activator.PLUGIN_ID, "icons/2.png");
/*
* (non-Javadoc)
*
* #see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
#Override
public void addListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub
// IResourceChangeEvent.POST_CHANGE
}
/*
* (non-Javadoc)
*
* #see org.eclipse.jface.viewers.IBaseLabelProvider#dispose()
*/
#Override
public void dispose() {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* #see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
*/
#Override
public boolean isLabelProperty(Object element, String property) {
// TODO Auto-generated method stub
return false;
}
/*
* (non-Javadoc)
*
* #see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
#Override
public void removeListener(ILabelProviderListener listener) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* #see org.eclipse.jface.viewers.ILightweightLabelDecorator#decorate(java.lang.Object, org.eclipse.jface.viewers.IDecoration)
*/
#Override
public void decorate(Object element, IDecoration decoration) {
if (some_condition)
decoration.addOverlay(OVERLAY1);
else
decoration.addOverlay(OVERLAY2);
}
}
You can ask the IDecoratorManager to update decorations with a specific id using:
IDecoratorManager decoratorManager = PlatformUI.getWorkbench().getDecoratorManager();
decoratorManager.update("decorator id");
To do this on file save you will have to use an IResourceChangeListener to listen to workspace resource changes and react when you see your file being changed.
Set up a listener with:
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener);
In the IResourceChangeListener you can do something like:
public void resourceChanged(IResourceChangeEvent event) {
IResourceDelta delta = event.getDelta();
IResourceDelta fileDelta = delta.findMember(IPath of file you are interested in);
if (fileDelta != null) {
// TODO handle the delta
}
}

TYPO3 extbase: how to use ObjectStorage?

I'm trying to use a m:n relation, the same way as FrontEndUser is related to FrontEndUserGroup, e.g. without intermediate mm table. In my controller, I build my object, then I call $barRepository->update($barObject); to update the values of my object. However, it fails on the update function with the error:
Fatal error: Call to undefined method Cbrunet\Up\Domain\Model\Foo::getPosition() in /home/cbrunet/websites/typo3_src-6.1.1/typo3/sysext/extbase/Classes/Persistence/Generic/Backend.php on line 486
where Foo is the type of the object contained in the ObjectStorage of Bar. My understanding is that getPosition should be called on the ObjectStorage, not on the object contained into that ObjectStorage. However, I cannot figure out why this is not working in my case.
This is in TYPO3 6.1.5. Any hint would be appreciated.
The model of Bar which has a m:n relation to Foo looks like:
namespace Cbrunet\Up\Domain\Model;
class Bar extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {
/**
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\Cbrunet\Up\Domain\Model\Foo>
*/
protected $myprop;
public function __construct() {
$this->myprop = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* #param \TYPO3\CMS\Extbase\Persistence\ObjectStorage $myprop
* #return void
*/
public function setMyprop(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $myprop) {
$this->myprop = $myprop;
}
/**
* #param \Cbrunet\Up\Domain\Model\Foo $myprop
* #return void
*/
public function addMyprop(\Cbrunet\Up\Domain\Model\Foo $myprop) {
$this->myprop->attach($myprop);
}
/**
* #param \Cbrunet\Up\Domain\Model\Foo $myprop
* #return void
*/
public function removeMyprop(\Cbrunet\Up\Domain\Model\Foo $myprop) {
$this->myprop->detach($myprop);
}
/**
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
*/
public function getMyprop() {
return $this->myprop;
}
}
The relevant code in my controller looks like:
/**
* action update
*
* #return void
*/
public function updateAction() {
$args = $this->request->getArgument('myargs');
foreach ($args as $k=>$val) {
$pp = $this->barRepository->findOneByAprop($k); // another prop of Bar, not illustrated in the code above.
$listepour = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
foreach ($val as $p) {
$ap = $this->fooRepository->findOneByUid(intval($p));
$listepour->attach($ap);
}
$pp->setMyprop($listepour);
$this->barRepository->update($pp); // error occurs here
}
$this->redirect('list');
}
Do you also have configured your TCA?
do you have an initStorageObjects-function in your domain model?
Also you can try to build these case with the extension-manager and compare the code.

Showing GWT validation errors using Editor Framework

I do GWT client side validation and I've a problem of how to show validation errors which are returned by validator. I debugged it and I can see that the set contains errors but driver doesn't show them. SimpleBeanEditorDriver is used.
Entry Entry = driver.flush();
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Entry>> violations = validator.validate(Entry, Default.class);
if (violations.size() > 0) {
driver.setConstraintViolations(new ArrayList<ConstraintViolation<?>>(violations));
...
}
Tested on GWT ver. 2.4 and 2.5
The code is written according to https://developers.google.com/web-toolkit/doc/latest/DevGuideValidation but they're not using editors.
Does anybody make it work together GWT validation and Editors ? May be somebody can give links to good examples of it ? I couldn't find any working ones. Any help are welcomed!
Here is a simple example of how we are using editors/HasEditorError and ConstraintViolations. I have also included a sample from our ValueBoxEditorDecorator which allows us to layout error message.
Our activity
#Override
public void onSave() {
RequestFactoryEditorDriver<DashboardModelProxy, ?> driver = display.getDriver();
RequestContext context = driver.flush();
context.fire(new Receiver<Void>() {
#Override
public void onSuccess(Void response) {
Place previousPlace = clientFactory.getPlaceController().getPreviousPlace();
clientFactory.getPlaceController().goTo(previousPlace);
}
#Override
public void onFailure(ServerFailure error) {
display.showError(error.getMessage());
}
#Override
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
display.getDriver().setConstraintViolations(violations);
}
});
}
Sample from our view.
/**
* Name component for the name of the analytics operation.
* This also implements {#link HasEditorErrors so it can show
* constraint violations when an error occurs.
*/
#UiField
ValueBoxEditorDecorator<String> name;
UIBinder example using the error location.
<t:ValueBoxEditorDecorator errorLocation="RIGHT" ui:field="name">
<t:valuebox>
<g:TextBox />
</t:valuebox>
</t:ValueBoxEditorDecorator>
The ValueBoxEditorDecorator we are using.
import java.util.List;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.editor.client.EditorError;
import com.google.gwt.editor.client.HasEditorErrors;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.adapters.TakesValueEditor;
import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
import com.google.gwt.uibinder.client.UiChild;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.ValueBoxBase;
import com.google.gwt.user.client.ui.ValueListBox;
/**
* This is a copy of the original ValueBoxEditorDecorator in the gwt source The
* reason we are not using it is because it did not support laying out the error
* panel in a different location.
*
*
* A simple decorator to display leaf widgets with an error message.
* <p>
* <h3>Use in UiBinder Templates</h3>
* <p>
* The decorator may have exactly one ValueBoxBase added though an
* <code><e:valuebox></code> child tag.
* <p>
* For example:
*
* <pre>
* #UiField
* ValueBoxEditorDecorator<String> name;
* </pre>
*
* <pre>
* <e:ValueBoxEditorDecorator ui:field='name'>
* <e:valuebox>
* <g:TextBox />
* </e:valuebox>
* </e:ValueBoxEditorDecorator>
* </pre>
*
* #param <T>
* the type of data being edited
*/
public class ValueListBoxEditorDecorator<T> extends Composite implements HasEditorErrors<T>, IsEditor<TakesValueEditor<T>> {
/**
* The location of the text relative to the paging buttons.
*/
public static enum ErrorPanelLocation {
LEFT, RIGHT;
}
SimplePanel contents = new SimplePanel();
#Ignore
Label errorLabel = new Label();
HorizontalPanel layout = new HorizontalPanel();
private TakesValueEditor<T> editor;
/**
* Constructs a ValueBoxEditorDecorator.
*/
#UiConstructor
public ValueListBoxEditorDecorator(ErrorPanelLocation errorLocation) {
initWidget(layout);
setStyleName("gwt-ValueBoxEditorDecorator");
errorLabel.setStyleName("gwt-ValueBoxEditorDecorator-error");
errorLabel.getElement().getStyle().setDisplay(Display.NONE);
if (errorLocation == ErrorPanelLocation.RIGHT) {
layout.add(contents);
layout.add(errorLabel);
} else {
layout.add(errorLabel);
layout.add(contents);
}
}
/**
* Constructs a ValueBoxEditorDecorator using a {#link ValueBoxBase} widget
* and a {#link ValueBoxEditor} editor.
*
* #param widget
* the widget
* #param editor
* the editor
*/
public ValueListBoxEditorDecorator(ValueListBox<T> widget, TakesValueEditor<T> editor) {
this(ErrorPanelLocation.RIGHT);
contents.add(widget);
this.editor = editor;
}
/**
* Returns the associated {#link ValueBoxEditor}.
*
* #return a {#link ValueBoxEditor} instance
* #see #setEditor(ValueBoxEditor)
*/
public TakesValueEditor<T> asEditor() {
return editor;
}
/**
* Sets the associated {#link ValueBoxEditor}.
*
* #param editor
* a {#link ValueBoxEditor} instance
* #see #asEditor()
*/
public void setEditor(ValueBoxEditor<T> editor) {
this.editor = editor;
}
/**
* Set the widget that the EditorPanel will display. This method will
* automatically call {#link #setEditor}.
*
* #param widget
* a {#link ValueBoxBase} widget
*/
#UiChild(limit = 1, tagname = "valuebox")
public void setValueBox(ValueBoxBase<T> widget) {
contents.add(widget);
setEditor(widget.asEditor());
}
public void clearErrors() {
errorLabel.setText("");
errorLabel.getElement().getStyle().setDisplay(Display.NONE);
}
/**
* The default implementation will display, but not consume, received errors
* whose {#link EditorError#getEditor() getEditor()} method returns the
* Editor passed into {#link #setEditor}.
*
* #param errors
* a List of {#link EditorError} instances
*/
public void showErrors(List<EditorError> errors) {
StringBuilder sb = new StringBuilder();
for (EditorError error : errors) {
if (error.getEditor().equals(editor)) {
sb.append("\n").append(error.getMessage());
}
}
if (sb.length() == 0) {
clearErrors();
return;
}
errorLabel.setText(sb.substring(1));
errorLabel.getElement().getStyle().setDisplay(Display.INLINE_BLOCK);
}
}
This wiki might help you:
https://github.com/apetrelli/gwt-integration/wiki/GWT-Integration-Editor
although it integrates Editor, Validator and RequestFactory.
I created a Maven archetype that uses it:
https://github.com/apetrelli/samplegwt

How to run some task after application window is created and visible?

I have SWT application. I need to run some task (with progress bar) after application started and its window is visible. How/Where to do that ?
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.StatusLineManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class TestApp extends ApplicationWindow {
/**
* Create the application window.
*/
public TestApp() {
super(null);
createActions();
addToolBar(SWT.FLAT | SWT.WRAP);
addMenuBar();
addStatusLine();
}
/**
* Create contents of the application window.
* #param parent
*/
#Override
protected Control createContents(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
return container;
}
/**
* Create the actions.
*/
private void createActions() {
// Create the actions
}
/**
* Create the menu manager.
* #return the menu manager
*/
#Override
protected MenuManager createMenuManager() {
MenuManager menuManager = new MenuManager("menu");
return menuManager;
}
/**
* Create the toolbar manager.
* #return the toolbar manager
*/
#Override
protected ToolBarManager createToolBarManager(int style) {
ToolBarManager toolBarManager = new ToolBarManager(style);
return toolBarManager;
}
/**
* Create the status line manager.
* #return the status line manager
*/
#Override
protected StatusLineManager createStatusLineManager() {
StatusLineManager statusLineManager = new StatusLineManager();
return statusLineManager;
}
/**
* Launch the application.
* #param args
*/
public static void main(String args[]) {
try {
TestApp window = new TestApp();
window.setBlockOnOpen(true);
window.open();
Display.getCurrent().dispose();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Configure the shell.
* #param newShell
*/
#Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText("New Application");
}
/**
* Return the initial size of the window.
*/
#Override
protected Point getInitialSize() {
return new Point(450, 300);
}
}
You could use a paint listener.
#Override
protected Control createContents(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
container.addPaintListener(new PaintListener() {
#Override
public void paintControl(PaintEvent e) {
System.out.println("I'm ready to go...");
}
});
return container;
}
Thanks to Tom for an idea of registering listener. I found something that works for me - ShellListener. Example below.
/**
* Create contents of the application window.
* #param parent
*/
#Override
protected Control createContents(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
// build gui...
getShell().addShellListener(new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
// some task...
}
});
return container;
}