I am working on an editor plugin for Eclipse that handles my own script language. In the editor, I have a hover that shows short information about element under the mouse cursor.
Now, I am trying to create a toolbar on the bottom of the hover and place a button there that will open a more detailed description online.
I have written my code based on answer to that question. The button is visible and it works when it is clicked.
However, it disappears a short time after I move my mouse over the hover. Why is this happening and how can I prevent that?
Here is the relevant part of my code:
#Override
public IInformationControlCreator getHoverControlCreator() {
return new IInformationControlCreator() {
#Override
public IInformationControl createInformationControl(final Shell parent) {
ToolBarManager tbm = new ToolBarManager(SWT.FLAT);
DefaultInformationControl defaultInformationControl = new DefaultInformationControl(parent, tbm);
Action action = new Action() {
#Override
public void run() {
MessageDialog.openInformation(parent, "omg", "It works.");
}
};
action.setText("123 test 321");
Bundle bundle = FrameworkUtil.getBundle(this.getClass());
URL url = FileLocator.find(bundle, new Path("icons/test.gif"), null);
action.setImageDescriptor(ImageDescriptor.createFromURL(url));
tbm.add(action);
tbm.update(true);
return defaultInformationControl;
}
};
}
When hover is created with DefaultInformationControl(parent, tbm) then toolbar is visible. However when you move mouse over the hover, then it gains focus. Then method getInformationPresenterControlCreator() from DefaultInformationControl is called.
It looks like (from source code):
public IInformationControlCreator getInformationPresenterControlCreator() {
return new IInformationControlCreator() {
/*
* #see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
*/
public IInformationControl createInformationControl(Shell parent) {
return new DefaultInformationControl(parent,
(ToolBarManager) null, fPresenter);
}
};
}
Look at return line. It nulls your Toolbar manager. That is the reason is gone.
Quick solution might be to create a new class which extends DefaultInformationControl and then in overrides
#Override
public IInformationControlCreator getInformationPresenterControlCreator() {
return new YourOwnInformationControlCreator();
}
This way you can pass correct ToolbarManager.
Related
I want the context menu items of my natTable to change, depending on the selected row. How can I achieve this ?
UPDATE: this works so far, i have A and B showing on even/uneven lines. My next question is: does this mean that I have to call these methods for every menu item groups ?
myPopupMenuBuilder.withMenuItemProvider("A", new IMenuItemProvider() {
#Override
public void addMenuItem(NatTable paramNatTable, Menu paramMenu) {
MenuItem row = new MenuItem(paramMenu, SWT.PUSH);
row.setText("A");
}
}).withMenuItemProvider("B", new IMenuItemProvider() {
#Override
public void addMenuItem(NatTable paramNatTable, Menu paramMenu) {
MenuItem row = new MenuItem(paramMenu, SWT.PUSH);
row.setText("B");
}
}).withVisibleState("A", new IMenuItemState() {
#Override
public boolean isActive(NatEventData paramNatEventData) {
return paramNatEventData.getRowPosition() % 2 == 0;
}
}).withVisibleState("B", new IMenuItemState() {
#Override
public boolean isActive(NatEventData paramNatEventData) {
return paramNatEventData.getRowPosition() % 2 == 1;
}
});
It depends on how you implement the context menu. If you use the NatTable way of registering a context menu (which I typically suggest) you can use PopupMenuBuilder#withEnabledState() or PopupMenuBuilder#withVisibleState(). Inside the implementation of IMenuItemState you get the position where the click was performed, which then can be used to get the underlying data.
More information can be found in my blog post about that topic: NatTable context menus with Eclipse menus
If you want to use E4 menus, you will have to implement some additional logic to extract the necessary information from the click with regards to the NatTable.
I am tring to create my own text hover plugin for eclipse.
I success to write my own code in my hover, but I try to add a toolbar to the hover (inside the new tooltip opened).
I read that I need to use the getHoverControlCreator function, and I managed to add the toolbar manager that I see when the text hover is opened while running the plugin,in the debbuger I can see that the ToolBarManger has the ToolBar that has the ToolItems, but I can't see them in the real text hover when I opened it.
this is my code:
public IInformationControlCreator getHoverControlCreator() {
return new IInformationControlCreator() {
public IInformationControl createInformationControl(Shell parent) {
ToolBar tb = new ToolBar(parent, SWT.HORIZONTAL);
ToolBarManager tbm = new ToolBarManager(tb);
DefaultInformationControl dic = new DefaultInformationControl(parent, tbm);
ToolItem ti = new ToolItem(tb, SWT.PUSH);
ti.setText("hello");
tb.update();
tb.redraw();
tbm.update(true);
parent.update();
parent.redraw();
parent.layout();
return dic;
}
This is what one of the Eclipse hover controls does:
#Override
public IInformationControl doCreateInformationControl(Shell parent) {
ToolBarManager tbm = new ToolBarManager(SWT.FLAT);
DefaultInformationControl iControl = new DefaultInformationControl(parent, tbm);
IAction action = new MyAction();
tbm.add(action);
tbm.update(true);
return iControl;
}
So it does not create the ToolBar - leave that up to DefaultInformationControl. It uses an Action in the tool bar and adds it after creating the DefaultInformationControl. It just calls update(true) at the end.
(This is a modified version of parts of org.eclipse.jdt.internal.ui.text.java.hover.NLSStringHover)
MyAction would be something like:
private class MyAction extends Action
{
MyAction()
{
super("Title", .. image descriptor ..);
setToolTipText("Tooltip");
}
#Override
public void run()
{
// TODO your code for the action
}
}
Using the Toolbar class within codenameone, how do I dynamically set the visibility of the SideMenuBar?
I'm using a WebBrowser component, and I only want the SideMenu to be accessible after login.
I achieved the behavior I wanted when I was simply placing commands on a SideMenuBar (METHOD 1), but now that I've switched over to use the Toolbar class for the LnF advantages (METHOD 2), the hideLeftSideMenuBool theme constant does not seem to be observed.
//METHOD 1
//CHANGING THE THEME DYNAMICALLY HIDES THE SIDEMENUBAR WHEN I'VE SIMPLY
//ADDED COMMANDS LIKE THIS
current.addCommand(new Command("Home") {
{
putClientProperty("place", "side");
}
});
//METHOD 2
//CHANGING THE THEME DYNAMICALLY DOES NOT HIDE THE SIDEMENUBAR WHEN I'VE
//USED toolbar.addComponentToSideMenu TO ADD BUTTONS WITH COMMANDS
toolbar = new Toolbar();
current.setToolbar(toolbar);
Button home = new Button("Home");
toolbar.addComponentToSideMenu(home, new Command("Home"){
#Override
public void actionPerformed(ActionEvent evt) {
wb.setURL(startURL);
}
});
...
//I USED THE FOLLOWING CODE TO DYNAMICALLY SET THE THEME AFTER EVALUATING A
//WebBrowser URI REGARDLESS OF WHICH METHOD WAS USED TO ADD COMMANDS
wb.setBrowserNavigationCallback(new BrowserNavigationCallback() {
public boolean shouldNavigate(String url) {
if ((url.indexOf("users/login") != -1)) {
try {
//theme_noside.res has hideLeftSideMenuBool set to true
theme = Resources.openLayered("/theme_noside");
UIManager.getInstance().setThemeProps(theme.getTheme(theme.getThemeResourceNames()[0]));
UIManager.getInstance().getLookAndFeel().setMenuBarClass(SideMenuBar.class);
Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_SIDE_NAVIGATION);
current.refreshTheme();
}catch(IOException e){
Log.p(e.toString());
}
}
else {
try {
//theme.res has hideLeftSideMenuBool set to false
theme = Resources.openLayered("/theme");
UIManager.getInstance().setThemeProps(theme.getTheme(theme.getThemeResourceNames()[0]));
UIManager.getInstance().getLookAndFeel().setMenuBarClass(SideMenuBar.class);
Display.getInstance().setCommandBehavior(Display.COMMAND_BEHAVIOR_SIDE_NAVIGATION);
current.refreshTheme();
}catch(IOException e){
Log.p(e.toString());
}
}
return true;
}
});
Use Toolbar api only and you don't have to call or change any theme constant.
Make your toolbar final or declare it outside the beforeShow() method, so you can access it within inner method shouldNavigate(String url).
All you need to do is call removeAll() and then reset the title and add components you want. If toolbar has no command or title, it would be hidden by default.
wb.setBrowserNavigationCallback(new BrowserNavigationCallback() {
public boolean shouldNavigate(String url) {
if ((url.indexOf("users/login") != -1)) {
toolbar.removeAll();
toolbar.setTitleComponent(new Label("My Form", "Title"));
toolbar.getComponentForm().revalidate();
} else {
//Do nothing, since I've already add the commands I want earlier
}
return true;
}
});
I have a piece of code where a function opens a popup window to later return an integer based on what happened inside that window. But when I run it, it directly returns the integer without opening any popup window.
How do I tell that function to wait to return until a user has done a certain action?
Here's the code in case you need it:
public int initPopup(String monsterName, String monsterHP){
final int monsterHPInt = Integer.parseInt(monsterHP);
PopupWindow popup;
TextView popupText;
Button closePopupButton;
final SeekBar monsterHPChanger;
LinearLayout popupLayout;
popupText = new TextView(this);
popupText.setText(monsterName);
monsterHPChanger = new SeekBar(this);
monsterHPChanger.setMax(monsterHPInt);
/** Will only use if necessary
* monsterHPChanger.setProgress(monsterHPChanger.getMax());
*/
popupLayout = new LinearLayout(this);
popupLayout.setOrientation(LinearLayout.VERTICAL);
popupLayout.addView(popupText);
popupLayout.addView(monsterHPChanger);
//TODO: Create the layout of the popup and the popup itself
popup = new PopupWindow(popupLayout, LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
popup.setContentView(popupLayout);
//Creating encapsulation class to edit the monsterHP with the value of the SeekBar
final MonsterHP monsterHPObject = new MonsterHP(monsterHPInt, monsterHPChanger.getProgress());
closePopupButton = new Button(this);
closePopupButton.setId(R.id.closePopup);
closePopupButton.setText("Ok");
closePopupButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
monsterHPObject.update(monsterHPChanger.getProgress());
}
});
Log.println(1, "Method", "Returns " + monsterHPObject.getHP());
// TODO: reactivate when debug is done return monsterHPObject.getHP();
//Returning 0 for debug reasons
return 0;
}
I'm looking your code and I dont see the call "popup.show()" anywhere. Also, if you want to wait some time to perform an operation you can use the following code.
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// your operations (open popup?)
}
}, **your_delay_time**);
Hope it helps you!!
Use a callback interface that you pass to your method.
When the user performs the action, call the appropriate callback method.
I want to make a drop down menu, like a status menu, that is hidden when the activity starts, and when it's pressed or slid it opens like the image below..
http://i.stack.imgur.com/jeq5z.png
My layout currently has a RelativeLayout for the top bar and a ScrollView for the text.. between those, i'd like to put the menu..
I'm not doing this app on phonegap or anything like that, just java and xml..
Thanks in advance
Edit:
Thank you all for your help! I end up doing a FrameLayout that was set off the screen with the translationY and then, when clicked, just slide up and down.. Here's the snipped.. I'll just leave it here in case someone else needs it.
on layout.xml
<FrameLayout
android:id="#+id/layout_FrameLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#00ffffff" >
<!-- stuf -->
</FrameLayout>
on activity.java
private FrameLayout statusDrawer = null;
private int statusDrawerHeight; // height of the FrameLayout (generated automatically)
private int statusDrawerDragButtonHeight = 30 + 5; //height of the DragButton + height of the border
private boolean statusDrawerOpened = false;
private int statusDrawerDuration = 750; //time in milliseconds
private TimeInterpolator interpolator = null; //type of animation see#developer.android.com/reference/android/animation/TimeInterpolator.html
#Override
protected void onCreated(Bundle savedInstanceState){
statusDrawer = (FrameLayout) findViewById(R.id.layout_FrameLayout);
interpolator = new AccelerateDecelerateInterpolator();
statusDrawer.post(new Runnable() {
#Override
public void run() {
statusDrawerHeight = statusDrawer.getHeight();
statusDrawer.setTranslationY(-statusDrawerHeight+statusDrawerDragButtonHeight);
}
});
statusDrawer.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
if(statusDrawerOpened) {
statusDrawer.animate()
.translationY(-statusDrawerHeight+statusDrawerDragButtonHeight)
.setDuration(statusDrawerDuration)
.setInterpolator(interpolator)
.start();
} else {
statusDrawer.animate()
.translationY(0)
.setDuration(statusDrawerDuration)
.setInterpolator(interpolator)
.start();
}
statusDrawerOpened = !statusDrawerOpened;
}
});
}
Use a FrameLayout as the root layout. Add the drop menu layout as in the right side of your picture. Call
menuView.setTranslationY(-view.getHeight);
on this view to initially hide the drop down menu when the activity is started. Make sure menuView only refers to the drop down view part without the small tab button. When the user touches the tab animate translationY to 0 so that the layout will slide down
ObjectAnimator.ofFloat(dropDownView, "translationY", -view.getHeight, 0).setDuration(200).start();
whereby dropDownView refers to the complete drop down menu.
Using ObjectAnimator requires API level 11. If you need to support older API levels, use http://developer.android.com/reference/android/view/animation/TranslateAnimation.html (which has some down sides).
If you instead want add a sliding effect, e.g. the sliding menu is moving with together with the finger, install a OnTouchListener:
dropDownTab.setOnTouchListener(new OnTouchListener() {
public void onTouch(View v, MotionEvent e) {
// Make the drop down menu finger follow the finger position.
// Use again dropDownView.setTranslationY(...) to move the view.
// If the drop down menu has been dragged a certain distance, make it move out by itself using the animation as above.
}
});