/*
* Copyright 2004 Perforce Software. All rights reserved.
*
* Developed by Data Shades Ltd.
*/
/*
* Functionality related to integrating the Perforce menu
* within Photoshop.
*/
#include <windows.h>
#include "P4GTPhotoshop.h"
#include "PerforceMenu.h"
#include "MenuState.h"
#include "InterfaceUtils.h"
#ifndef LANG_ja
#include "PluginNewMessages.h"
#else
#include "PluginNewMessages_ja.h"
#endif
/*
* Photoshop main window proc.
*/
static WNDPROC photoshopWndProc;
/*
* Handle to Perforce menu
*/
static HMENU perforceMenu = NULL;
/*
* Photoshop file types
*/
static StrBufArray fileTypes;
/*
* Setup Photoshop file types
*/
void InitFileTypes()
{
fileTypes.Put( _T("Photoshop files (*.PSD;*.PDD)") );
fileTypes.Put( _T("BMP (*.BMP;*.RLE;*.DIB)") );
fileTypes.Put( _T("Camera Raw (*.TIF;*.CRW;*.NEF;*.RAF;*.ORF;*.DCR;*.MOS)") );
fileTypes.Put( _T("Cineon (*.CIN;*.SDPX;*.DPX;*.FIDO)") );
fileTypes.Put( _T("CompuServe GIF (*.GIF)") );
fileTypes.Put( _T("Photoshop EPS (*.EPS)") );
fileTypes.Put( _T("Photoshop DCS 1.0 (*.EPS)") );
fileTypes.Put( _T("Photoshop DCS 2.0 (*.EPS)") );
fileTypes.Put( _T("EPS TIFF Preview (*.EPS)") );
fileTypes.Put( _T("Filmstrip (*.FLM)") );
fileTypes.Put( _T("JPEG (*.JPG;*.JPEG;*.JPE)") );
fileTypes.Put( _T("Large Document Format (*.PSB)") );
fileTypes.Put( _T("Generic PDF (*.PDF;*.PDP;*.AI)") );
fileTypes.Put( _T("Generic EPS (*.AI3;*.AI4;*.AI5;*.AI6;*.AI7;*.AI8;*.PS;*.EPS;*.AI;*.EPSF;*.EPSP)") );
fileTypes.Put( _T("PCX (*.PCX)") );
fileTypes.Put( _T("Photoshop PDF (*.PDF;*.PDP)") );
fileTypes.Put( _T("Acrobat TouchUp Image (*.PDF;*.AI;*.PDP)") );
fileTypes.Put( _T("Photo CD (*.PCD)") );
fileTypes.Put( _T("Photoshop Raw (*.RAW)") );
fileTypes.Put( _T("PICT File (*.PCT;*.PICT)") );
fileTypes.Put( _T("Pixar (*.PXR)") );
fileTypes.Put( _T("PNG (*.PNG)") );
fileTypes.Put( _T("Scitex CT (*.SCT)") );
fileTypes.Put( _T("Targa (*.TGA;*.VDA;*.ICB;*.VST)") );
fileTypes.Put( _T("TIFF (*.TIF;*.TIFF)") );
fileTypes.Put( _T("Wireless Bitmap (*.WBMP;*.WBM)") );
fileTypes.Put( _T("All Files (*.*)") );
}
/*
* Set menu option to be checked or not
*
* option - The id of the menu option
* checked - If true then check otherwise clear
*/
void CheckMenuOption( UINT option, BOOL checked )
{
MENUITEMINFO menuInfo;
menuInfo.cbSize = sizeof( MENUITEMINFO );
menuInfo.fMask = MIIM_STATE;
menuInfo.fState = checked ? MFS_CHECKED : MFS_UNCHECKED ;
SetMenuItemInfo( perforceMenu, option, FALSE, &menuInfo ) ;
}
/*
* Set menu option to be grayed out or enabled
*
* option - The id of the menu option
* enabled - True if enabled, false if grayed
*/
void EnableMenuOption( UINT option, bool enabled )
{
MENUITEMINFO menuInfo;
menuInfo.cbSize = sizeof( MENUITEMINFO );
menuInfo.fMask = MIIM_STATE;
menuInfo.fState = enabled ? MFS_ENABLED : MFS_GRAYED ;
SetMenuItemInfo( perforceMenu, option, FALSE, &menuInfo ) ;
}
/*
* Set menu option label
*
* option - The id of the menu option
* label - The label to use
*/
void SetMenuLabel( UINT option, TCHAR *label )
{
MENUITEMINFO menuInfo;
menuInfo.cbSize = sizeof( MENUITEMINFO );
menuInfo.fMask = MIIM_TYPE;
menuInfo.fType = MFT_STRING;
menuInfo.dwTypeData = label;
menuInfo.cch = _tcslen( menuInfo.dwTypeData );
SetMenuItemInfo( perforceMenu, option, FALSE, &menuInfo );
}
/*
* About to show Perforce menu so need to p4 stat current file and
* see what menu options need to be grayed out etc.
*/
void ChangeMenuState()
{
MenuState *state = perforceOps->GetMenuState();
EnableMenuOption( ID_ADD_TO_PERFORCE, state->AddEnabled() );
EnableMenuOption( ID_CHECK_OUT, state->CheckOutEnabled() );
EnableMenuOption( ID_CHECK_IN, state->CheckInEnabled() );
EnableMenuOption( ID_DOCUMENT_STATUS, state->DocumentStatusEnabled() );
EnableMenuOption( ID_DOCUMENT_HISTORY, state->DocumentHistoryEnabled() );
EnableMenuOption( ID_UNLOCK, state->LockUnlockEnabled() );
EnableMenuOption( ID_UNDO, state->UndoEnabled() );
EnableMenuOption( ID_LAST_RESULTS, state->ResultsEnabled() );
EnableMenuOption( ID_CHECKED_OUT, state->CheckedOutEnabled() );
EnableMenuOption( ID_INFORMATION, state->InfoEnabled() );
EnableMenuOption( ID_OPEN_DEPOT, state->OpenEnabled() );
SetMenuLabel( ID_ONLINE, state->EnableDisableLabel() );
SetMenuLabel( ID_UNLOCK, state->LockUnlockLabel() );
SetMenuLabel( ID_UNDO, state->UndoLabel() );
delete state;
}
/*
* Create the Perforce menu
*/
HMENU CreatePerforceMenu()
{
HMENU menu = CreatePopupMenu();
AppendMenu( menu, MF_STRING, ID_ADD_TO_PERFORCE, P4_MENU_ADD );
AppendMenu( menu, MF_STRING, ID_CHECK_OUT, P4_MENU_CHECKOUT );
AppendMenu( menu, MF_STRING, ID_CHECK_IN, P4_MENU_CHECKIN );
AppendMenu( menu, MF_STRING, ID_UNLOCK, P4_MENU_LOCK_UNLOCK );
AppendMenu( menu, MF_STRING, ID_UNDO, P4_MENU_UNDO_ADD );
AppendMenu( menu, MF_SEPARATOR, 0, NULL );
AppendMenu( menu, MF_STRING, ID_LAST_RESULTS, P4_MENU_RESULT_CMD );
AppendMenu( menu, MF_STRING, ID_DOCUMENT_STATUS, P4_MENU_DOC_STAT );
AppendMenu( menu, MF_STRING, ID_DOCUMENT_HISTORY, P4_MENU_DOC_HIST );
AppendMenu( menu, MF_STRING, ID_CHECKED_OUT, P4_MENU_DOC_CHECKED_OUT );
AppendMenu( menu, MF_STRING, ID_INFORMATION, P4_MENU_SERVER_INFO );
AppendMenu( menu, MF_SEPARATOR, 0, NULL );
AppendMenu( menu, MF_STRING, ID_OPEN_DEPOT, P4_MENU_GET_LATEST );
AppendMenu( menu, MF_SEPARATOR, 0, NULL );
AppendMenu( menu, MF_STRING, ID_OPTIONS, P4_MENU_OPTIONS );
AppendMenu( menu, MF_STRING, ID_HELP, P4_MENU_HELP );
AppendMenu( menu, MF_STRING, ID_ABOUT, P4_MENU_ABOUT );
AppendMenu( menu, MF_SEPARATOR, 0, NULL );
AppendMenu( menu, MF_STRING, ID_ONLINE, P4_MENU_SERVER_ONLINE );
return menu;
}
bool IsMenuInstalled() {
HWND win = host->GetWin();
HMENU menu = GetMenu( win );
HMENU sub = GetSubMenu(menu, 1);
if (sub == perforceMenu) {
return true;
}
else {
return false;
}
}
HWND InstallMenu() {
// Insert Perforce menu into main menu
HWND win = host->GetWin();
HMENU menu = GetMenu( win );
InsertMenu( menu, 1, MF_STRING | MF_POPUP | MF_BYPOSITION, (UINT)perforceMenu, P4_MENU_PERFORCE );
return win;
}
/*
* Our new main window proc.
*/
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch (uMsg) {
case WM_COMMAND:
// Reset the close flag
host->SetClosing( false );
// Check for menu option selection
switch ( LOWORD(wParam) ) {
case ID_ADD_TO_PERFORCE:
perforceOps->Add();
return 0;
case ID_CHECK_OUT:
perforceOps->Edit();
return 0;
case ID_CHECK_IN:
perforceOps->Submit();
return 0;
case ID_UNLOCK:
perforceOps->ToggleLock();
return 0;
case ID_UNDO:
perforceOps->Revert();
return 0;
case ID_LAST_RESULTS:
perforceOps->ShowLastResults();
return 0;
case ID_DOCUMENT_STATUS:
perforceOps->ShowStatus();
return 0;
case ID_DOCUMENT_HISTORY:
perforceOps->ShowHistory();
return 0;
case ID_CHECKED_OUT:
perforceOps->ShowOpenFiles();
return 0;
case ID_INFORMATION:
perforceOps->ShowInfo();
return 0;
case ID_OPTIONS:
perforceOps->ShowOptions();
return 0;
case ID_HELP:
perforceOps->ShowHelp();
return 0;
case ID_OPEN_DEPOT:
if ( fileTypes.Count() == 0 ) {
InitFileTypes();
}
perforceOps->ShowOpenDepot( &fileTypes );
return 0;
case ID_ABOUT:
perforceOps->ShowAbout();
return 0;
case ID_ONLINE:
perforceOps->ToggleOnline();
return 0;
case ID_APP_QUIT:
host->SetClosing( true );
break;
}
break;
/*
* Get this when menu is about to show.
*/
case WM_INITMENUPOPUP:
if (perforceMenu == (HMENU)wParam) {
ChangeMenuState();
}
break;
case WM_SETFOCUS:
// Sometimes the menu can be lost after receiving this message
// but not in Photoshop CS3 and later.
//
char asciibuff[MAX_HOST_VERSION];
UTIL_Version( asciibuff );
// Only for releases prior to Photoshop CS3.
if (strncmp((char *)asciibuff+19, "10", 2) < 0 ) {
if ( perforceMenu != NULL && !IsMenuInstalled() ) {
InstallMenu();
}
}
break;
case WM_CLOSE:
host->SetClosing( true );
// User closed ugly dialog
if ( host->GetWin() )
DestroyWindow( host->GetWin() );
perforceMenu = NULL;
break;
}
/*
* Forward messages to Photoshop
*/
LRESULT ret = CallWindowProc( photoshopWndProc, hWnd, uMsg, wParam, lParam );
// Check if we are shutting down (because doing a system shutdown
if ( uMsg == WM_QUERYENDSESSION && ret ) {
// Need to restore old wndproc here to avoid a crash when
// shutting down windows.
RemovePerforceWndProc();
}
return ret;
}
/*
* Subclass Photoshop window
*/
void InstallPerforceWndProc()
{
HWND win = host->GetWin();
#ifdef OS_NTX64
photoshopWndProc = ( WNDPROC )SetWindowLongPtr( win, GWLP_WNDPROC, ( DWORD_PTR )MainWndProc );
#else
photoshopWndProc = ( WNDPROC )SetWindowLong( win, GWL_WNDPROC, ( LONG )MainWndProc );
#endif // OS_NTX64
// Insert the perforce menu
if ( perforceMenu == NULL) {
perforceMenu = CreatePerforceMenu();
HWND win = InstallMenu();
// Need to refresh main menu to get our menu to show
DrawMenuBar( win );
}
}
/*
* Restore Photoshop window proc.
*/
void RemovePerforceWndProc()
{
HWND win = host->GetWin();
// Check if window exists before setting plug-in windows
// procedure address.
if ( IsWindow( win ) ) {
#ifdef OS_NTX64
SetWindowLongPtr( win, GWLP_WNDPROC, ( DWORD_PTR )photoshopWndProc );
#else
SetWindowLong( win, GWL_WNDPROC, ( LONG )photoshopWndProc );
#endif // OS_NTX64
}
}