How to implement a three dot menu in cuba platform? - cuba-platform

How can I implement a vertical three dot menu in every table row, like here in this picture?

CUBA.platform has no built-in component that provides context menu on button click, but it can be easily implemented using Vaadin ContextMenu class.
The main concept is as follows:
unwrap Vaadin component:
CubaButton vButton = button.unwrap(CubaButton.class);
create a context menu for this component and add menu items:
ContextMenu contextMenu = new ContextMenu(vButton, true);
contextMenu.addItem("Item", (MenuBar.Command) selectedItem -> {
// handle menu item click
});
...
show the context menu programmatically on button click:
vButton.setClickHandler(clickEvent ->
contextMenu.open(clickEvent.getClientX(), clickEvent.getClientY()));
You can use this approach in the generated table column. Let's assume that we need a single-column table that displays all the data.
XML definition
<table id="usersTable"
dataContainer="usersDc"
columnHeaderVisible="false"
stylename="no-stripes"
width="250px"
height="400px">
<columns>
<column id="column"/>
</columns>
<buttonsPanel>
<button caption="Share" icon="USER_PLUS" stylename="borderless"/>
<button caption="Preview" icon="EYE" stylename="borderless"/>
</buttonsPanel>
</table>
Java Controller
#UiController("demo_Sandbox")
#UiDescriptor("sandbox.xml")
public class Sandbox extends Screen {
#Inject
private UiComponents uiComponents;
#Inject
private Notifications notifications;
#Inject
private MetadataTools metadataTools;
#Install(to = "usersTable.column", subject = "columnGenerator")
private Component usersTableColumnColumnGenerator(User user) {
HBoxLayout rootLayout = uiComponents.create(HBoxLayout.class);
rootLayout.setMargin(new MarginInfo(true, false, true, false));
rootLayout.setSpacing(true);
rootLayout.setWidthFull();
VBoxLayout content = uiComponents.create(VBoxLayout.class);
content.setSpacing(true);
Label<String> login = uiComponents.create(Label.TYPE_STRING);
login.setValue("Login: " + user.getLogin());
Label<String> name = uiComponents.create(Label.TYPE_STRING);
name.setValue("Name: " + user.getName());
content.add(login, name);
LinkButton contextMenu = uiComponents.create(LinkButton.class);
contextMenu.setIconFromSet(CubaIcon.ELLIPSIS_V);
contextMenu.setAlignment(Alignment.TOP_RIGHT);
setupContextMenu(contextMenu, user);
rootLayout.add(content, contextMenu);
return rootLayout;
}
private void setupContextMenu(LinkButton button, User user) {
CubaButton vButton = button.unwrap(CubaButton.class);
ContextMenu contextMenu = new ContextMenu(vButton, true);
addMenuItem(contextMenu, "Rename", user);
addMenuItem(contextMenu, "Delete", user);
addMenuItem(contextMenu, "Open", user);
vButton.setClickHandler(clickEvent ->
contextMenu.open(clickEvent.getClientX(), clickEvent.getClientY()));
}
private void addMenuItem(ContextMenu contextMenu, String caption, User user) {
contextMenu.addItem(caption, (MenuBar.Command) selectedItem ->
notifications.create()
.withCaption(caption + ": " + metadataTools.getInstanceName(user))
.show());
}
}
The result

Related

How to hide stacklayout if user clicked somwhere else on screen

I createt ResourceDictionary in App.xaml file for application header.
In header I created two dropdowns menu (with stacklayouts and grids).
First is for some user informations and second one is for search.
By default these dropdown menus are hiden.
Max one may be visible if user click on user-icon or on search-icon.
So in HeaderViewModel I cratet these two methods:
private async void AccountInformationAsync()
{
var userService = await UserService.GetUserData();
Username = userService.Username;
DisplayName = userService.DisplayName;
Status = userService.Status;
Influence = userService.Influence;
MTP = userService.MTP;
VisibilityInformation = !VisibilityInformation;
if (VisibilityInformation == true)
{
VisibilitySearch = false;
}
}
private void Search()
{
VisibilitySearch = !VisibilitySearch;
if (VisibilitySearch == true)
{
VisibilityInformation = false;
}
}
This works fine... If user click on user-icon user info will show up and if user then click on serach-icon info will hide an search menu will show up.
So, my question is how to hide any of these menus if user click somewhere else on the screen?
You need to add an TapGestureRecognizer on the Main Layout View of the Page. And on the Tap of it you can use Command and Hide both the dropdown Menu.
private void HideDropDowns()
{
VisibilitySearch = false;
VisibilityInformation = false;
}
HideDropDowns should be the Method assigned to the Command in the TapGestureRecognizer.

intellij plugin development show input dialog with multiple text boxes

I'm creating intelliJ plugin and registering my action , inside my action i want to show an input dialog with multiple text boxes, how do I do that ?
I have an example of showing only one text box -
String txt= Messages.showInputDialog(project, "What is your name?",
"Input your name", Messages.getQuestionIcon());
I agree with #AKT with extending the DialogWrapper but suggest overriding doOKAction:
#Override
protected void doOKAction() {
if (getOKAction().isEnabled()) {
// custom logic
System.out.println("custom ok action logic");
close(OK_EXIT_CODE);
}
}
Or, if you just want your data out without the Action mess, add a custom method:
public class SearchDialog extends DialogWrapper {
...
public String getQuery() {
return "my custom query";
}
}
You can use it like:
SearchDialog dialog = new SearchDialog();
dialog.showAndGet(); // Maybe check if ok or cancel was pressed
String myQuery = dialog.getQuery();
System.out.println("my query: " + myQuery);
Create a new GUI Form (form + class). Class should extend DialogWrapper and override methods.
Inside createCenterPanel() return your root JPanel. You can set any default values, add event listeners to text box, etc., before returning JPanel.
Implement an Action interface where you want to get the value when OK button is clicked. Pass this action to your form class.
getOKAction() should return this action.
Following code is from a plugin i'm currently working on. Hopefully this will give you some idea but will have to adapt it to your need.
public class ReleaseNoteDialog extends DialogWrapper implements Action {
private JTextArea txtReleaseNote;
private JPanel panelWrapper;
.......
protected JComponent createCenterPanel() {
......
return panelWrapper;
}
......
#Override
protected Action getOKAction() {
return this;
}
.......
#Override
public void actionPerformed(ActionEvent e) {
// save value to project state
super.doOKAction();
}

How to use active class when login or Register link clicked

I am using one mvc 4 application where i used bootstrap class.Now i used one html helper class to check if any actionlink menu is clicked there it set class active.
Now the issue is with Navbar brand link and login and register link.
I can't use the same html helper class for these because it is having some extra properties used like below code:
#Html.ActionLink("Application name", "Index", "Home", null, new { #class = "navbar-brand" })
<li>#Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>#Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
Above first link is header which should be by default active.
and other one are login and register which should be active after clicked.
I have got some idea from internet which is first i created one #html helper class which is like below:
public static MvcHtmlString MenuLink(this HtmlHelper helper,string text, string action, string controller)
{
var routeData = helper.ViewContext.RouteData.Values;
var currentController = routeData["controller"];
var currentAction = routeData["action"];
if (String.Equals(action, currentAction as string,
StringComparison.OrdinalIgnoreCase)
&&
String.Equals(controller, currentController as string,
StringComparison.OrdinalIgnoreCase))
{
return new MvcHtmlString("<li class=\"active\">" + helper.ActionLink(text, action, controller) + "</li>");
}
return new MvcHtmlString("<li>" + helper.ActionLink(text, action, controller) + "</li>");
}
Then i called this class in my menu links like below:
#Html.MenuLink("Home", "Index", "Home")
So after click on this link it is setting as active.
Thanks everyone for helped me.

Is it somehow possible to have two master views and one detail view?

If I have for example one master view on the left and one in the middle, each showing oder Java Beans/POJOs, can I use a shared detail view that somehow listens to the active beans of each view and then displays the currently selected one in more detail? A one to one relation is quite easy to manage by using your Context library.
#ViewDocking(areaId ="left", position=1, displayName="Profiles", menuEntry = #WindowMenuEntry(path = "", position=0), accelerator="Shortcut+1")
public class ProfileListView extends BorderPane implements LocalContextProvider {
private final SimpleContextContent content = new SimpleContextContent();
private final SimpleContext context = new SimpleContext(content);
#FXML
private ListView<Profile> listview;
public ProfileListView() {
load();
// add some profiles
listview.getItems().add(new Profile("Profile1"));
listview.getItems().add(new Profile("Profile2"));
listview.getItems().add(new Profile("Profile3"));
// setup selection listener
listview.getSelectionModel().selectedItemProperty().addListener((value, oldProfile, newProfile) -> {
// set active profile and remove old one
content.remove(oldProfile);
content.add(newProfile);
});
// setup double click listener
configureClickListener();
}
private Profile getSelectedProfile() {
return listview.getSelectionModel().getSelectedItem();
}
private void configureClickListener() {
listview.setOnMouseClicked(event -> {
// check if it was a double click
if(event.getClickCount() == 2) {
System.out.println(getSelectedProfile());
// inject into editor pane
// calls the procedure to create a tab in the center area...
}
});
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
}
This is one master view holding a list view of items.
The other one would be the same, docking to the right as another tab and holding POJOs of type 'Action'.
The detail view is here:
#ViewDocking(areaId = "right", displayName = "Properties", accelerator = "Shortcut+2", menuEntry = #WindowMenuEntry(path = "", position = 0), position = 1)
public class ProfilePropertiesView extends BorderPane implements LocalContextProvider, ActiveContextSensitive {
private Context activeContext;
private SimpleContextContent content = new SimpleContextContent();
private SimpleContext context = new SimpleContext(content);
private Profile profile;
private IWindowService service = new NullWindowService();
#FXML
private PropertySheet propertysheet;
public ProfilePropertiesView() {
load();
// retrieve framework service, TODO: use tracker
BundleContext ctx = FrameworkUtil.getBundle(getClass()).getBundleContext();
service = ctx.getService(ctx.getServiceReference(IWindowService.class));
// initialize callback
service.addCallback(title -> {
System.out.println("callback called " + title);
// update the property sheet ui by re-creating the items list
// updateUI();
// we can safely return null
return null;
});
// configure editor factory so the user is able to use a combobox
propertysheet.setPropertyEditorFactory(new CustomPropertyEditorFactory(service));
}
private void load() {
FXMLLoaders.loadRoot(this);
}
#Override
public Context getLocalContext() {
return context;
}
private void contextChanged() {
// find profile information
Profile found = activeContext.find(Profile.class);
// if the found profile is null, ignore it
if (found != null) {
// reset if profile is valid
if (profile != null) {
reset();
}
// create reference and register
profile = found;
register();
}
}
private void register() {
// retrieve observablelist of bean properties if some profile is selected
if(profile != null) {
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().setAll(items);
}
}
private void updateUI() {
// clear property elements and re-create them
reset();
// re-create items
ObservableList<Item> items = createDetailedList(profile);
propertysheet.getItems().addAll(items);
}
private ObservableList<Item> createDetailedList(Object bean) {
ObservableList<Item> list = FXCollections.observableArrayList();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);
Arrays.stream(beanInfo.getPropertyDescriptors()).map(pd -> new DetailedBeanProperty(bean, pd)).forEach(list::add);
} catch (IntrospectionException e) {
e.printStackTrace();
}
return list;
}
private void reset() {
propertysheet.getItems().clear();
}
#Override
public void setActiveContext(Context activeContext) {
this.activeContext = activeContext;
this.activeContext.addContextListener(Profile.class, event -> contextChanged());
// trigger change
contextChanged();
}
}
The current ProfilePropertiesView is just configured to display the properties of the selected profile. I want it to be able to display the current information of the last selected POJO in the UI. That means that if the user selected a Profile from the ListView, that profile should be displayed in the properties view. If he selected an Action from the Table (which is displayed in the center), the properties of the Action should be displayed.
Do I just need to register a new ContextListener for the Action.class
POJO and then call a method to populate the PropertiesView? I was
unsure if this is the right solution...
Yes, just add another ContextListener to the activeContext for every POJO type you want to observe.
Also note that in the constructor of views it's better to use a ServiceTracker instead of looking for the service via BundleContext as the service might not be available yet, depending on the order the bundles are loaded.
You can find a sample which uses a ServiceTracker here: https://stackoverflow.com/a/35974498/506855

Default Button - Vb.NET

I have a button that I want to make default, but without the border thing around the button. Is this possible to do?
Thanks.
The visual cue comes as standard if you set the default button. You could, however, do something with key-preview, capturing carriage-return and performing the required action(s) necessary. To give a C# example (same concepts apply to VB.NET):
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Button btn1, btn2;
using(Form form = new Form {
Controls = {
(btn1 = new Button { Dock = DockStyle.Bottom, Text = "Button 1"}),
(btn2 = new Button { Dock = DockStyle.Bottom, Text = "Button 2"}),
new TextBox { Dock = DockStyle.Fill, Text = "just text"}
}
})
{
btn1.Click += delegate {form.Text = "button 1 clicked";};
btn2.Click += delegate {form.Text = "button 2 clicked";};
form.KeyPreview = true;
form.KeyDown += (sender, args) =>
{
if (args.KeyCode == Keys.Return) btn1.PerformClick();
};
Application.Run(form);
}
}