/******************************************************************************* * Copyright (c) 2006-2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * IBM Research *******************************************************************************/ package com.ibm.research.cue.tourist.internal.win32.ppt; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.ole.win32.OleAutomation; import org.eclipse.swt.ole.win32.OleClientSite; import org.eclipse.swt.ole.win32.OleFrame; import org.eclipse.swt.ole.win32.Variant; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import com.ibm.research.cue.tourist.internal.win32.ppt.api.DocumentWindow; import com.ibm.research.cue.tourist.internal.win32.ppt.api.MsoTriState; import com.ibm.research.cue.tourist.internal.win32.ppt.api.PpSlideShowRangeType; import com.ibm.research.cue.tourist.internal.win32.ppt.api.PpSlideShowType; import com.ibm.research.cue.tourist.internal.win32.ppt.api.PpWindowState; import com.ibm.research.cue.tourist.internal.win32.ppt.api.Presentations; import com.ibm.research.cue.tourist.internal.win32.ppt.api.SlideShowSettings; import com.ibm.research.cue.tourist.internal.win32.ppt.api.SlideShowWindows; import com.ibm.research.cue.tourist.internal.win32.ppt.api.Slides; import com.ibm.research.cue.tourist.internal.win32.ppt.api.View; import com.ibm.research.cue.tourist.internal.win32.ppt.api._Application; import com.ibm.research.cue.tourist.internal.win32.ppt.api._Presentation; import com.ibm.research.cue.tourist.internal.win32.ppt.api._Slide; /** * front-end to manipulating powerpoint from java. note that powerpoint is minimized by default. call show() to reveal it * * @tag fixed powerpoint : currently, powerpoint can only be floating, not embedded if we want to access all of the functionality * * @author Li-Te Cheng * CUE, IBM Research, 2006 */ public class PowerpointApplication { private OleFrame frame; private OleClientSite clientSite; private _Application application; private Timer fDisposeTimer; private Menu menubar; private _Presentation activePresentation; private SlideShowSettings settings; private SlideShowWindows slideShowWindows; private List<IPowerpointApplicationListener> listeners = new ArrayList<IPowerpointApplicationListener>(); /** * internal initialization of OLE stuff, UI, and dispose handlers * @param parent * @param style */ private void init(Composite parent, int style) { frame = new OleFrame(parent,style); // @tag fixed powerpoint : using "Powerpoint.Slide" will let us embed, but DOES NOT give access to _Application API clientSite = new OleClientSite(frame,SWT.NONE,"Powerpoint.Application"); application = new _Application(new OleAutomation(clientSite)); frame.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { // clean up all OLE automation stuff if ( application!=null ) application.dispose(); } }); // @tag powerpoint menu : SWT.BAR style bit enables access to powerpoint menu bar if ( (style & SWT.BAR)!=0 ) { menubar = frame.getShell().getMenuBar(); if ( menubar==null ) { menubar = new Menu(frame.getShell(),SWT.BAR); frame.getShell().setMenuBar(menubar); } } // minimize powerpoint by default application.setWindowState(new Variant(PpWindowState.ppWindowMinimized)); // powerpoint must be visible in order to manipulate it application.setVisible(new Variant(MsoTriState.msoTrue)); } /** * constructor - sets up powerpoint, associated with given composite * * @param parent * @param style : SWT.NONE or SWT.BAR (enables access to powerpoint menu bar) */ public PowerpointApplication(Composite parent, int style) { init(parent,style); } /** * reveal powerpoint UI in normal state */ public void show() { application.setWindowState(new Variant(PpWindowState.ppWindowNormal)); } /** * kill powerpoint application */ public void quit() { application.Quit(); clientSite.dispose(); frame.dispose(); } /** * maxmimize powerpoint UI */ public void maximize() { application.setWindowState(new Variant(PpWindowState.ppWindowMaximized)); } /** * minimize powerpoint UI */ public void minimize() { application.setWindowState(new Variant(PpWindowState.ppWindowMinimized)); } /** * retrieves powerpoint menu bar if SWT.BAR was set as style bit in constructor * @return Menu */ public Menu getMenuBar() { return menubar; } /** * retrieves OleFrame - need this to place menu bar changes back into powerpoint window (see main() for example) * @return OleFrame */ public OleFrame getOleFrame() { return frame; } /** * checks if the active presentation as specified. useful for preventing multiple "read-only" copies of the same presentation from opening. * * @tag powerpoint tours fixed : limitation - only works for active presentation. need to make this work for multiple different presentations * * @param filename * @return boolean */ public boolean isActive(String filename) { if ( application.getActivePresentation()==null ) return false; _Presentation activePresentation = new _Presentation(application.getActivePresentation().getAutomation()); Variant fullName = activePresentation.getFullName(); boolean result = (fullName==null)?false:fullName.getString().equals(filename); activePresentation.dispose(); return result; } /** * loads a powerpoint presentation * @param filename */ public void open(String filename) { Presentations presentations = new Presentations(application.getPresentations().getAutomation()); presentations.Open(filename); presentations.dispose(); } /** * saves currently active powerpoint presentation * @param filename */ public void save(String filename) { _Presentation activePresentation = new _Presentation(application.getActivePresentation().getAutomation()); activePresentation.SaveAs(filename); activePresentation.dispose(); } /** * navigates powerpoint to specified slide in slide editor (not in slide show mode) * @param n - slide # */ public void gotoEditorSlide(int n) { DocumentWindow activeWindow = new DocumentWindow(application.getActiveWindow().getAutomation()); View view = new View(activeWindow.getView().getAutomation()); view.GotoSlide(n); view.dispose(); activeWindow.dispose(); } /** * runs a powerpoint slide show - this method will block until the show is finished * * @param startingSlide * @param endingSlide */ public void runSlideShow(int startingSlide, int endingSlide) { activePresentation = new _Presentation(application.getActivePresentation().getAutomation()); settings = new SlideShowSettings(activePresentation.getSlideShowSettings().getAutomation()); slideShowWindows = new SlideShowWindows(application.getSlideShowWindows().getAutomation()); settings.setShowType(new Variant(PpSlideShowType.ppShowTypeSpeaker)); settings.setRangeType(new Variant(PpSlideShowRangeType.ppShowSlideRange)); settings.setStartingSlide(new Variant(startingSlide)); settings.setEndingSlide(new Variant(endingSlide)); settings.Run(); hookDisposeTimer(); } /** * runs a powerpoint slide show - this method will block until the show is finished */ public void runSlideShow() { activePresentation = new _Presentation(application.getActivePresentation().getAutomation()); settings = new SlideShowSettings(activePresentation.getSlideShowSettings().getAutomation()); slideShowWindows = new SlideShowWindows(application.getSlideShowWindows().getAutomation()); settings.setShowType(new Variant(PpSlideShowType.ppShowTypeSpeaker)); settings.setRangeType(new Variant(PpSlideShowRangeType.ppShowAll)); settings.Run(); hookDisposeTimer(); } public void hookDisposeTimer() { if(fDisposeTimer!=null) fDisposeTimer.cancel(); fDisposeTimer = new Timer(); fDisposeTimer.schedule(new TimerTask() { @Override public void run() { Display.getDefault().asyncExec(new Runnable() { public void run() { // current slide window is null when the slide show is over. assumes this thread gets executed right after the first slide appears on the screen if (activePresentation!=null && activePresentation.getSlideShowWindow()==null) { for (IPowerpointApplicationListener listener : listeners) listener.slideShowEnded(); endSlideShow(); } } }); } }, 0, 100); } public void endSlideShow() { if(slideShowWindows!=null) { slideShowWindows.dispose(); slideShowWindows = null; } if(settings!=null) { settings.dispose(); settings = null; } if(activePresentation!=null) { activePresentation.dispose(); activePresentation = null; } if(fDisposeTimer!=null) { fDisposeTimer.cancel(); fDisposeTimer = null; for (IPowerpointApplicationListener listener : listeners) listener.endSlideShowCalled(); } } public void addPowerpointApplicationListener(IPowerpointApplicationListener listener) { if ( !listeners.contains(listener) ) listeners.add(listener); } public void removePowerpointApplicationListener(IPowerpointApplicationListener listener) { listeners.remove(listener); } /** * returns slide # of the slide currently in the powerpoint editor * @return slide number or -1 on failure */ public int getCurrentEditorSlide() { int n = -1; DocumentWindow activeWindow = new DocumentWindow(application.getActiveWindow().getAutomation()); View view = new View(activeWindow.getView().getAutomation()); Variant vSlide = view.getSlide(); if ( vSlide!=null ) { _Slide slide = new _Slide(vSlide.getAutomation()); Variant vSlideNum = slide.getSlideNumber(); n = vSlideNum.getInt(); slide.dispose(); } view.dispose(); activeWindow.dispose(); return n; } /** * returns number of slides in the active presentation loaded in the powerpoint editor * @return slide number of -1 on failure */ public int getCount() { int n = -1; _Presentation activePresentation = new _Presentation(application.getActivePresentation().getAutomation()); Slides slides = new Slides(activePresentation.getSlides().getAutomation()); Variant vCount = slides.getCount(); n = vCount.getInt(); slides.dispose(); activePresentation.dispose(); return n; } /** * test program * @param args */ public static void main(String[] args) { // example of PowerpointFrame in action final Display display = new Display(); final Shell shell = new Shell(display); final PowerpointApplication ppt = new PowerpointApplication(shell,SWT.BAR); shell.setText("powerpoint application test program"); Menu bar = ppt.getMenuBar(); MenuItem fileBarItem = new MenuItem(bar,SWT.CASCADE); fileBarItem.setText("Test"); Menu fileMenu = new Menu(fileBarItem); fileBarItem.setMenu(fileMenu); MenuItem openItem = new MenuItem(fileMenu,SWT.CASCADE); openItem.setText("&Open"); openItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { FileDialog openDialog = new FileDialog(shell,SWT.OPEN); String filename = openDialog.open(); if ( filename!=null ) { ppt.open(filename); ppt.show(); } } } ); MenuItem saveItem = new MenuItem(fileMenu,SWT.CASCADE); saveItem.setText("&Save"); saveItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { FileDialog saveDialog = new FileDialog(shell,SWT.SAVE); String filename = saveDialog.open(); if ( filename!=null ) ppt.save(filename); } } ); MenuItem allItem = new MenuItem(fileMenu,SWT.CASCADE); allItem.setText("Show all slides"); allItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ppt.runSlideShow(); } } ); MenuItem gotoItem = new MenuItem(fileMenu,SWT.CASCADE); gotoItem.setText("Show slide x"); gotoItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { InputDialog dialog = new InputDialog(shell,"show slide","enter a slide #","1",null); if ( dialog.open() == Window.OK ) { String value = dialog.getValue(); int slideNum = Integer.parseInt(value); ppt.runSlideShow(slideNum, slideNum); } } } ); MenuItem editorItem = new MenuItem(fileMenu,SWT.CASCADE); editorItem.setText("Goto slide x in editor"); editorItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { InputDialog dialog = new InputDialog(shell,"goto slide in editor","enter a slide #","1",null); if ( dialog.open() == Window.OK ) { String value = dialog.getValue(); int slideNum = Integer.parseInt(value); ppt.gotoEditorSlide(slideNum); } } } ); MenuItem slidenumItem = new MenuItem(fileMenu,SWT.CASCADE); slidenumItem.setText("Get current slide # in editor"); slidenumItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { int n = ppt.getCurrentEditorSlide(); MessageDialog.openInformation(shell, "current slide #", "current slide in editor = " + n); } } ); MenuItem quitItem = new MenuItem(fileMenu,SWT.CASCADE); quitItem.setText("kill powerpoint"); quitItem.addSelectionListener( new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { ppt.quit(); } } ); OleFrame frame = ppt.getOleFrame(); frame.setFileMenus(new MenuItem[] {fileBarItem} ); shell.setLayout( new FillLayout() ); shell.open(); while ( !shell.isDisposed() ) { if ( !display.readAndDispatch() ) display.sleep(); } } }