@Override
	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {
		StyledText styledText = viewer.getTextWidget();
		if (styledText == null) {
			return;
		}
		
		final Shell browserShell = new Shell(shell, SWT.APPLICATION_MODAL);
		browserShell.setLayout(new FillLayout());
		
		final Browser browser = new Browser(browserShell, SWT.NONE);

		browserShell.addFocusListener(new FocusListener() {
			
			@Override
			public void focusLost(FocusEvent e) { }
			
			@Override
			public void focusGained(FocusEvent e) {
				// we don't want the shell getting focus
				// so before processing the next event in the event loop (see below)
				// set the focus to the browser...
				fixFocus = true;
			}
		});
		
		browserShell.addTraverseListener(new TraverseListener() {

			@Override
			public void keyTraversed(TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_ESCAPE) {
					cancelled = true;
				}
			}
			
		});

		// Set the default size
		browserShell.setSize(this.initWidth >= 0 ? this.initWidth : DEFAULT_WIDTH,
				this.initHeight >= 0 ? this.initHeight : DEFAULT_HEIGHT);
		
		// Add Graphite API functions
		new ResizeToFunction(browserShell, browser, GRAPHITE_PREFIX + "resizeTo");
		new ResizeByFunction(browserShell, browser, GRAPHITE_PREFIX + "resizeBy");
		new InsertFunction(this, browserShell, browser, GRAPHITE_PREFIX + "insert");
		new CancelFunction(browserShell, browser, GRAPHITE_PREFIX + "cancel");
		new GetIDEFunction(browser, GRAPHITE_PREFIX + "getIDE");
		new GetLanguageFunction(browser, GRAPHITE_PREFIX + "getLanguage");
		new GetSelectedText(browser, GRAPHITE_PREFIX + "getSelectedText", viewer.getDocument(), viewer.getSelectedRange());

		// move the palette into position
		movePalette(styledText, browserShell);
		
		// show the browser
		browser.setUrl(this.url);
		browserShell.open();
					
		// drop into event loop until the browser shell is disposed
		Display display = shell.getDisplay();
	    while (!browserShell.isDisposed()) {
	    	if (fixFocus) {
	    		fixFocus = false;
	    		browser.setFocus();
	    	}
	    	boolean done = display.readAndDispatch();
	    	if (!done) display.sleep();
	    }
	    
	    // See if the dialog was closed by ESC key.
	    if (this.cancelled) {
	    	return;
	    }
	    
	    // Insert replacement string
	    String completion = this.completion; 
	    if (completion != null) {
	    	super.setReplacementString(completion);
	    	super.setCursorPosition(completion.length());
	    }
	    
		super.apply(viewer, trigger, stateMask, offset);
	}