How to show a Safari Extension popover programmatically - safari-extension

I'm trying to write a Safari extension that consists of a button on the main toolbar with a popover tied to it, and a contextual menu item. The basic feel is modeled after the feel of the 1Password extension.
One of the jobs of the popover is to allow a person to log in. I'm also conditionally changing the action of the contextual menu item, and if a who person isn't logged in clicks the menu item I would like to show the popover allowing them to log in, but I can't find a way to do this in the developer guides.
How do I "show" a popover?

If you only have one toolbar item and one popover (and never plan to add more), then it's just one line. Assuming you've already assigned the popover to the toolbar item in Extension Builder, you can just use:
safari.extension.toolbarItems[0].showPopover();
But if you have more than one popover and (potentially) more than one toolbar item, here's a generalized function to open a popover, specified by its identifier, under the specified toolbar item in the active browser window:
function showPopover(popoverId, toolbarItemId) {
var toolbarItem = safari.extension.toolbarItems.filter(function (tbi) {
return tbi.identifier == toolbarItemId && tbi.browserWindow == safari.application.activeBrowserWindow;
})[0];
var popover = safari.extension.popovers.filter(function (po) {
return po.identifier == popoverId;
})[0];
toolbarItem.popover = popover;
toolbarItem.showPopover();
}

Related

MenuItem disabled after turning off the view

I set up a project with two view controllers connected to two xibs (MainMenu.xib and MasterVC.xib)
In my MasterVC I programatically add NSMenuItems with actions (located in MasterVC) to a menu, that is located in MainMenu.xib (and is connected to AppDelegate).
let menuItem = NSMenuItem()
menuItem.title = object.name!
menuItem.keyEquivalent = object.shortcut!
menuItem.representedObject = object
menuItem.action = "testSelector:"
appDel.menu.insertItem(menuItem, atIndex: 0)
func testSelector(sender: NSMenuItem) {
let object = (sender.representedObject as! MyNewObject)
print("Name of set:", object.name)
}
My added menu items work (are enabled) as long as I have window from MasterVC opened. As soon as I close it I can't click those menu items (they are disabled).
Is there a way to keep them enabled all the time?
You need to do two steps in your storyboard or XIB file (whichever contains the main menu):
1)
Use the Attribute Inspector after selecting the menu and then turn off "Auto Enable Items" checkbox:
]
2)
And for each menu item you want to have enabled, select that menu item and use the Attributes Inspector to make sure this checkbox is set to on:
]

Custom context menu XAML for WP8

I try to implement a custom ContextMenu in a LongListSelector.
I'm not using the ContextMenu from Microsoft.Phone.Controls.Toolkit, it's basically the same as in the Rowi App:
(source: hiddenpineapple.com)
Approach 1
My list item toggles a VisualState on hold and an overlay is shown with controls in it.
The problem
I can't find a way to go back to the default state when the user clicks outside of the list item (as in the default ContextMenu).
Approach 2
I've implemented a custom template for the toolkit ContextMenu which looks exactly the same. I had to move its margin top to -itemHeight, as by default it is below the item.
The problem
The problem with this solution is, that it automatically closes itself when opening and I couldn't figure out how to avoid this.
Another problem was that it didn't work well with TiltEffect.IsTiltEnabled from the Toolkit (visual problems).
I need your help
Any suggestions on how to get this working?
Answer
Thanks to Cheese, now I know how to properly close the menu when the user clicks outside.
His suggestion was to get the coordinates of a Tap event on the current page, and check if it's inside the menu. When not, close the menu.
So I added a Tap listener to the page when the menu opens, and removed it when the menu closes. From the page listener I got the event coordinates and could check if it's inside the control which holds the menu (same size and position). I received the position of the control with Point leftUpperPoint = control.TransformToVisual(page).Transform(new Point(0, 0)) and the rightLowerPoint by adding the ActualWidth and ActualHeight.
But then I realized:
Why should I even calculate if the tap is inside the menu? I always want to close the menu when the user taps anywhere on the screen. If it's outside, yes. If it's on a menu button, yes.
Another modification I made was to listen for MouseLeftButtonDown instead of Tap as it also triggers when the user swipes.
So I removed this code and came up with the following:
private void ToggleMenu(object sender, System.Windows.Input.GestureEventArgs e)
{
PhoneApplicationFrame frame = ((PhoneApplicationFrame)Application.Current.RootVisual);
VisualState state = this.States.CurrentState;
if (state == null || state.Name == "DefaultState")
{
frame.MouseLeftButtonDown += MouseDownDelegate;
this.State = "MenuState";
}
else
{
frame.MouseLeftButtonDown -= MouseDownDelegate;
this.State = "DefaultState";
}
}
private void MouseDownDelegate(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
ToggleMenu(sender, null);
}
This works perfectly!
Thanks to Cheese for the hint.
Something like this by #denniscode http://dotnet.dzone.com/articles/rowi-show-tap-menu
Approach 1 problem
The best solution would be:
Get the menus coordinates, when user makes a tap - you check are tap coordinates on menu or not, if not - dissmiss - simple.
Approach 2 problem
I guess you had some button in a corner and when you tapped on it - nothing happened? And when you dissmissed the Tilt all worked. It seems that tilt works faster than a click, so, tilt changes the button coordinates, and device thiks you have missed/or dragged off
You can use what #ScottIsAFool suggested and maybe create another Dependency Property on your TapMenu control of type UIElement named CloseWhenTappedElement and automatically listen for Tap events inside your control once set. For example
<Grid x:Name="TapArea"/>
<TapMenu CloseWhenTappedElement="{Binding ElementName=TapArea"}/>

how to click on action bar menu items in test app that having only apk using robotium

I am testing APK file. I dont have source code. I need to click on the action bar menu item
I have tried solo.clickonActionbaritems option and it did not work. Please help me. Many thanks!
I guess you want to click on Android Menu button:
Find your keycode here
solo.sendKey(KeyEvent.KEYCODE_MENU);
Also I highly recommend to use Hierarchy viewer in DDMS to find id of required button.
View requiredButton = getViewById(id.reqired_button_id);
solo.clickOnView(requiredButton);
// Method returns view
protected View getViewById(int id) {
View view = solo.getView(id);
assertNotNull("View is null", view);
assertTrue("View is not shown", view.isShown());
return view;
}
Also you can use clickOnText.

Connecting Multiple NSMenuItems with Actions and State Variables

I'm not sure how to describe what I need but I'll give it a try, via an example :
Let's say we have a window and a sidebar, and want to toggle it (I mean the sidebar : on/off).
Now, let's also say that :
The user may toggle the sidebar via an item at the Main menu (e.g. Show Sidebar / Hide Sidebar)
The user may also toggle the sidebar via a button
And there is also another item, in some other menu, to do the very same thing (Show/Hide Sidebar)
What would be the most practical Cocoa-friendly approach to achieve that?
Of course, that means that, e.g. :
When somebody clicks the button, apart from the sidebar (showing or hiding), the menu items must now be showing the current status of the sidebar (e.g. "Show sidebar" must now turn to "Hide Sidebar" in all possible instances within menus, etc)
I hope you get the idea; it's definitely not something difficult; but I'm definitely confused on how I could use all of Cocoa's tricks to do it fast.
Thanks!
I'm assuming you have some controller object which implements an action -toggleSidebar:, and that both menus target the same controller. Also, in the controller, you keep an instance variable BOOL isSidebarShown.
Make your controller implement the NSUserInterfaceValidations protocol. Something like this:
- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem
{
if (anItem.action == #selector(toggleSidebar:) && [anItem isKindOfClass:[NSMenuItem class]])
{
NSString* title = isSidebarShown ? #"Hide Sidebar" : #"Show Sidebar";
[(NSMenuItem*)anItem setTitle:title];
}
return YES; // either way, the menu item is enabled
}

Dynamic popup menu for all views

I need to provide a dynamic popup menu for all views. I can create a dynamic popup menu contributibution, but I must set the URI and register it for certain view. Now I'm trying to register the menu dynamically, when the user selects another view:
public class GlobalSelectionListener implements ISelectionListener {
HashSet<IWorkbenchPart> extended = new HashSet<IWorkbenchPart>();
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (!extended.contains(part)) {
IWorkbenchPartSite wps = part.getSite();
if (wps == null)
return;
//creates popup menu for this part
MenuManager mgr = new MenuManager();
mgr.add(new DynamicMenu()); //DynamicMenu extends ContributionItem
wps.registerContextMenu("identifier." + mgr.hashCode(), mgr, wps.getSelectionProvider());
extended.add(part);
System.out.println(part + " menu extended");
}
}
}
But this does not work. No one menu item appears in popup menu. I don't know, whether is it ever possible to do it this way. Is there any method to add popup menu for arbitrary view dynamically? It seems, that the registerContextMenu() method does something else.
The problem was not solved, nevertheless there is a workaround. It is possible to register the pop-up menu in plugin.xml file for all views and editors needed. Usualy the number of plugin usecases is limited. If you're writting a plugin, you know what you need the plugin for. Use the Spy plug-in (ALT+SHIFT+F1) to see the active menu contribution identifiers and register your contribution to the pop-up menu of all views and editors you need.