diff options
author | Shashank | 2017-05-29 12:40:26 +0530 |
---|---|---|
committer | Shashank | 2017-05-29 12:40:26 +0530 |
commit | 0345245e860375a32c9a437c4a9d9cae807134e9 (patch) | |
tree | ad51ecbfa7bcd3cc5f09834f1bb8c08feaa526a4 /modules/scinotes/src | |
download | scilab_for_xcos_on_cloud-0345245e860375a32c9a437c4a9d9cae807134e9.tar.gz scilab_for_xcos_on_cloud-0345245e860375a32c9a437c4a9d9cae807134e9.tar.bz2 scilab_for_xcos_on_cloud-0345245e860375a32c9a437c4a9d9cae807134e9.zip |
CMSCOPE changed
Diffstat (limited to 'modules/scinotes/src')
181 files changed, 41175 insertions, 0 deletions
diff --git a/modules/scinotes/src/c/.deps/.dirstamp b/modules/scinotes/src/c/.deps/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/c/.deps/.dirstamp diff --git a/modules/scinotes/src/c/.deps/libsciscinotes_algo_la-ScilabKeywords.Plo b/modules/scinotes/src/c/.deps/libsciscinotes_algo_la-ScilabKeywords.Plo new file mode 100755 index 000000000..84ccec005 --- /dev/null +++ b/modules/scinotes/src/c/.deps/libsciscinotes_algo_la-ScilabKeywords.Plo @@ -0,0 +1,112 @@ +src/c/libsciscinotes_algo_la-ScilabKeywords.lo: src/c/ScilabKeywords.c \ + /usr/include/stdc-predef.h \ + ../../modules/core/includes/getvariablesname.h \ + ../../modules/core/includes/BOOL.h \ + ../../modules/core/includes/commandwords.h \ + ../../modules/core/includes/getfunctionslist.h \ + ../../modules/functions/includes/getmacroslist.h \ + ../../modules/functions/includes/dynlib_functions.h \ + ../../modules/core/includes/BOOL.h src/c/ScilabKeywords.h \ + ../../modules/core/includes/MALLOC.h \ + ../../modules/core/includes/sci_mem_alloc.h /usr/include/stdlib.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap-16.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/select2.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-float.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib.h + +/usr/include/stdc-predef.h: + +../../modules/core/includes/getvariablesname.h: + +../../modules/core/includes/BOOL.h: + +../../modules/core/includes/commandwords.h: + +../../modules/core/includes/getfunctionslist.h: + +../../modules/functions/includes/getmacroslist.h: + +../../modules/functions/includes/dynlib_functions.h: + +../../modules/core/includes/BOOL.h: + +src/c/ScilabKeywords.h: + +../../modules/core/includes/MALLOC.h: + +../../modules/core/includes/sci_mem_alloc.h: + +/usr/include/stdlib.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/select2.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib.h: diff --git a/modules/scinotes/src/c/.dirstamp b/modules/scinotes/src/c/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/c/.dirstamp diff --git a/modules/scinotes/src/c/.libs/libsciscinotes_algo_la-ScilabKeywords.o b/modules/scinotes/src/c/.libs/libsciscinotes_algo_la-ScilabKeywords.o Binary files differnew file mode 100755 index 000000000..1b9229861 --- /dev/null +++ b/modules/scinotes/src/c/.libs/libsciscinotes_algo_la-ScilabKeywords.o diff --git a/modules/scinotes/src/c/DllmainSCINOTES.c b/modules/scinotes/src/c/DllmainSCINOTES.c new file mode 100755 index 000000000..89967839e --- /dev/null +++ b/modules/scinotes/src/c/DllmainSCINOTES.c @@ -0,0 +1,33 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +#include <windows.h> +/*--------------------------------------------------------------------------*/ +#pragma comment(lib,"../../../../bin/libintl.lib") +/*--------------------------------------------------------------------------*/ +int WINAPI DllMain (HINSTANCE hInstance , DWORD reason, PVOID pvReserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_PROCESS_DETACH: + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + } + return 1; +} +/*--------------------------------------------------------------------------*/ + diff --git a/modules/scinotes/src/c/ScilabKeywords.c b/modules/scinotes/src/c/ScilabKeywords.c new file mode 100755 index 000000000..d0591bfc1 --- /dev/null +++ b/modules/scinotes/src/c/ScilabKeywords.c @@ -0,0 +1,70 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +/*--------------------------------------------------------------------------*/ +#include "getvariablesname.h" +#include "commandwords.h" +#include "getfunctionslist.h" +#include "getmacroslist.h" +#include "BOOL.h" +#include "ScilabKeywords.h" +#include "MALLOC.h" +/*--------------------------------------------------------------------------*/ +char **GetVariablesName(void) +{ + int returnedArraySize = 0; + char **VarsName = getVariablesName(&returnedArraySize, TRUE); + /* SWIG char array must be finished by NULL */ + if (VarsName) + { + VarsName = (char**)REALLOC(VarsName, sizeof(char*) * (returnedArraySize + 1)); + VarsName[returnedArraySize] = NULL; + } + return VarsName; +} +/*--------------------------------------------------------------------------*/ +char **GetCommandsName(void) +{ + int returnedArraySize = 0; + char **CommandKeywords = getcommandkeywords(&returnedArraySize); + if (CommandKeywords) + { + CommandKeywords = (char**)REALLOC(CommandKeywords, sizeof(char*) * (returnedArraySize + 1)); + CommandKeywords[returnedArraySize] = NULL; + } + return CommandKeywords; +} +/*--------------------------------------------------------------------------*/ +char **GetFunctionsName(void) +{ + int returnedArraySize = 0; + char **FunctionsName = GetFunctionsList(&returnedArraySize); + if (FunctionsName) + { + FunctionsName = (char**)REALLOC(FunctionsName, sizeof(char*) * (returnedArraySize + 1)); + FunctionsName[returnedArraySize] = NULL; + } + return FunctionsName; +} +/*--------------------------------------------------------------------------*/ +char **GetMacrosName(void) +{ + int returnedArraySize = 0; + char **MacrosName = getmacroslist(&returnedArraySize); + if (MacrosName) + { + MacrosName = (char**)REALLOC(MacrosName, sizeof(char*) * (returnedArraySize + 1)); + MacrosName[returnedArraySize] = NULL; + } + return MacrosName; +} +/*--------------------------------------------------------------------------*/ diff --git a/modules/scinotes/src/c/ScilabKeywords.h b/modules/scinotes/src/c/ScilabKeywords.h new file mode 100755 index 000000000..cabf079be --- /dev/null +++ b/modules/scinotes/src/c/ScilabKeywords.h @@ -0,0 +1,42 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +/*--------------------------------------------------------------------------*/ +#ifndef __SCILABKEYWORDS_H__ +#define __SCILABKEYWORDS_H__ + +/** +* Get all variables name in scilab +* @return char array +*/ +char **GetVariablesName(void); + +/** +* Get all commands name in scilab +* @return char array +*/ +char **GetCommandsName(void); + +/** +* get primitives name in scilab +* @return char array +*/ +char **GetFunctionsName(void); + +/** +* get macros name in scilab +* @return char array +*/ +char **GetMacrosName(void); + +#endif /* __SCILABKEYWORDS_H__ */ +/*--------------------------------------------------------------------------*/ diff --git a/modules/scinotes/src/c/core_Import.def b/modules/scinotes/src/c/core_Import.def new file mode 100755 index 000000000..620f5fc75 --- /dev/null +++ b/modules/scinotes/src/c/core_Import.def @@ -0,0 +1,15 @@ +LIBRARY core.dll + + +EXPORTS +; +callFunctionFromGateway +getScilabMode +com_ +freeArrayOfWideString +getVariablesName +getcommandkeywords +GetFunctionsList +MyHeapAlloc +MyHeapFree +MyHeapRealloc diff --git a/modules/scinotes/src/c/libsciscinotes_algo_la-ScilabKeywords.lo b/modules/scinotes/src/c/libsciscinotes_algo_la-ScilabKeywords.lo new file mode 100755 index 000000000..b80b614b9 --- /dev/null +++ b/modules/scinotes/src/c/libsciscinotes_algo_la-ScilabKeywords.lo @@ -0,0 +1,12 @@ +# src/c/libsciscinotes_algo_la-ScilabKeywords.lo - a libtool object file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/libsciscinotes_algo_la-ScilabKeywords.o' + +# Name of the non-PIC object +non_pic_object=none + diff --git a/modules/scinotes/src/c/scinotes.rc b/modules/scinotes/src/c/scinotes.rc new file mode 100755 index 000000000..50bcb3f8c --- /dev/null +++ b/modules/scinotes/src/c/scinotes.rc @@ -0,0 +1,96 @@ +// Microsoft Visual C++ generated resource script. +// + + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +//#include "afxres.h" +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// French (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +#ifdef _WIN32 +LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 5,5,2,0 + PRODUCTVERSION 5,5,2,0 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040c04b0" + BEGIN + VALUE "FileDescription", "scinotes module" + VALUE "FileVersion", "5, 5, 2, 0" + VALUE "InternalName", "scinotes module" + VALUE "LegalCopyright", "Copyright (C) 2017" + VALUE "OriginalFilename", "scinotes.dll" + VALUE "ProductName", "scinotes module" + VALUE "ProductVersion", "5, 5, 2, 0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x40c, 1200 + END +END + +#endif // French (France) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/modules/scinotes/src/c/scinotes.vcxproj b/modules/scinotes/src/c/scinotes.vcxproj new file mode 100755 index 000000000..54a30313a --- /dev/null +++ b/modules/scinotes/src/c/scinotes.vcxproj @@ -0,0 +1,264 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{BAE68B54-2C1A-44D0-A0E9-05156A784E79}</ProjectGuid> + <RootNamespace>scinotes</RootNamespace> + <Keyword>Win32Proj</Keyword> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>MultiByte</CharacterSet> + <WholeProgramOptimization>false</WholeProgramOptimization> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>MultiByte</CharacterSet> + <WholeProgramOptimization>false</WholeProgramOptimization> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>DynamicLibrary</ConfigurationType> + <CharacterSet>MultiByte</CharacterSet> + <PlatformToolset>v110</PlatformToolset> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup> + <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)bin\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)bin\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)bin\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental> + <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)bin\</OutDir> + <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)$(Configuration)\</IntDir> + <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">sci$(ProjectName)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">sci$(ProjectName)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">sci$(ProjectName)</TargetName> + <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">sci$(ProjectName)</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>.;../jni;../../../../java/jdk/include;../../../../java/jdk/include/win32;../../../../libs/intl;../../includes;../../../api_scilab/includes;../../../core/includes;../../../localization/includes;../../../jvm/includes;../../../output_stream/includes;../cpp;../../../functions/includes;../../../fileio/includes;../../../commons/src/jni;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;FORDLL;_DEBUG;_WINDOWS;_USRDLL;SCINOTES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> + </ClCompile> + <PreLinkEvent> + <Message>Make dependencies</Message> + <Command>lib /DEF:"$(ProjectDir)core_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform) /OUT:"$(ProjectDir)core.lib" 1>NUL 2>NUL +</Command> + </PreLinkEvent> + <Link> + <AdditionalDependencies>..\..\..\..\bin\scilocalization.lib;core.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(SolutionDir)bin\sci$(ProjectName).dll</OutputFile> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <ImportLibrary>$(SolutionDir)bin\sci$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Midl> + <TargetEnvironment>X64</TargetEnvironment> + </Midl> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>.;../jni;../../../../java/jdk/include;../../../../java/jdk/include/win32;../../../../libs/intl;../../includes;../../../api_scilab/includes;../../../core/includes;../../../localization/includes;../../../jvm/includes;../../../output_stream/includes;../cpp;../../../functions/includes;../../../fileio/includes;../../../commons/src/jni;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;FORDLL;_DEBUG;_WINDOWS;_USRDLL;SCINOTES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> + </ClCompile> + <PreLinkEvent> + <Message>Make dependencies</Message> + <Command>lib /DEF:"$(ProjectDir)core_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform) /OUT:"$(ProjectDir)core.lib" 1>NUL 2>NUL +</Command> + </PreLinkEvent> + <Link> + <AdditionalDependencies>core.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(SolutionDir)bin\sci$(ProjectName).dll</OutputFile> + <GenerateDebugInformation>true</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <ImportLibrary>$(SolutionDir)bin\sci$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX64</TargetMachine> + <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <WholeProgramOptimization>false</WholeProgramOptimization> + <AdditionalIncludeDirectories>.;../jni;../../../../java/jdk/include;../../../../java/jdk/include/win32;../../../../libs/intl;../../includes;../../../api_scilab/includes;../../../core/includes;../../../localization/includes;../../../jvm/includes;../../../output_stream/includes;../cpp;../../../functions/includes;../../../fileio/includes;../../../commons/src/jni;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;FORDLL;NDEBUG;_WINDOWS;_USRDLL;SCINOTES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> + </ClCompile> + <PreLinkEvent> + <Message>Make dependencies</Message> + <Command>lib /DEF:"$(ProjectDir)core_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform) /OUT:"$(ProjectDir)core.lib" 1>NUL 2>NUL +</Command> + </PreLinkEvent> + <Link> + <AdditionalDependencies>..\..\..\..\bin\scilocalization.lib;core.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(SolutionDir)bin\sci$(ProjectName).dll</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <ImportLibrary>$(SolutionDir)bin\sci$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX86</TargetMachine> + <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Midl> + <TargetEnvironment>X64</TargetEnvironment> + </Midl> + <ClCompile> + <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed> + <WholeProgramOptimization>false</WholeProgramOptimization> + <AdditionalIncludeDirectories>.;../jni;../../../../java/jdk/include;../../../../java/jdk/include/win32;../../../../libs/intl;../../includes;../../../api_scilab/includes;../../../core/includes;../../../localization/includes;../../../jvm/includes;../../../output_stream/includes;../cpp;../../../functions/includes;../../../fileio/includes;../../../commons/src/jni;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;FORDLL;NDEBUG;_WINDOWS;_USRDLL;SCINOTES_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <DisableSpecificWarnings>4251;%(DisableSpecificWarnings)</DisableSpecificWarnings> + </ClCompile> + <PreLinkEvent> + <Message>Make dependencies</Message> + <Command>lib /DEF:"$(ProjectDir)core_import.def" /SUBSYSTEM:WINDOWS /MACHINE:$(Platform) /OUT:"$(ProjectDir)core.lib" 1>NUL 2>NUL +</Command> + </PreLinkEvent> + <Link> + <AdditionalDependencies>core.lib;%(AdditionalDependencies)</AdditionalDependencies> + <OutputFile>$(SolutionDir)bin\sci$(ProjectName).dll</OutputFile> + <GenerateDebugInformation>false</GenerateDebugInformation> + <SubSystem>Windows</SubSystem> + <OptimizeReferences>true</OptimizeReferences> + <EnableCOMDATFolding>true</EnableCOMDATFolding> + <ImportLibrary>$(SolutionDir)bin\sci$(ProjectName).lib</ImportLibrary> + <TargetMachine>MachineX64</TargetMachine> + <CLRUnmanagedCodeCheck>true</CLRUnmanagedCodeCheck> + <RandomizedBaseAddress>false</RandomizedBaseAddress> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="..\cpp\callscinotes.cpp" /> + <ClCompile Include="DllmainSCINOTES.c" /> + <ClCompile Include="..\..\sci_gateway\c\gw_scinotes.c" /> + <ClCompile Include="..\..\sci_gateway\cpp\sci_closeSciNotesFromScilab.cpp" /> + <ClCompile Include="..\..\sci_gateway\cpp\sci_scinotes.cpp" /> + <ClCompile Include="ScilabKeywords.c" /> + <ClCompile Include="..\jni\ScilabKeywords_wrap.c" /> + <ClCompile Include="..\jni\SciNotes.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\includes\callscinotes.h" /> + <ClInclude Include="..\..\includes\dynlib_scinotes.h" /> + <ClInclude Include="..\..\includes\gw_scinotes.h" /> + <ClInclude Include="ScilabKeywords.h" /> + <ClInclude Include="..\jni\SciNotes.hxx" /> + </ItemGroup> + <ItemGroup> + <None Include="..\..\locales\scinotes.pot" /> + <None Include="core_import.def" /> + <None Include="..\jni\ScilabKeywords.i" /> + <None Include="..\..\Makefile.am" /> + <None Include="..\..\scinotes.iss" /> + <None Include="..\..\sci_gateway\scinotes_gateway.xml" /> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="scinotes.rc" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\..\tools\Dumpexts\Dumpexts.vcxproj"> + <Project>{3170e4c2-1173-4264-a222-7ee8ccb3ddf7}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\..\..\api_scilab\api_scilab.vcxproj"> + <Project>{43c5bab1-1dca-4743-a183-77e0d42fe7d0}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\..\..\commons\src\c\commons.vcxproj"> + <Project>{eca09a1e-6d12-4a47-92e1-a671c181df77}</Project> + </ProjectReference> + <ProjectReference Include="..\..\..\fileio\fileio.vcxproj"> + <Project>{4fc72d4a-80ee-4b1a-8724-0201c1a35621}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\..\..\functions\src\c\functions.vcxproj"> + <Project>{53a01263-92be-4c87-aa9a-79297f882310}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\..\..\jvm\libjvm.vcxproj"> + <Project>{8ba2dda8-bd04-4d4d-8ee6-6caa955f7470}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\..\..\localization\src\localization.vcxproj"> + <Project>{ecffeb0c-1eda-45ee-9a10-b18143852e17}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + <ProjectReference Include="..\..\..\output_stream\src\c\output_stream.vcxproj"> + <Project>{a5911cd7-f8e8-440c-a23e-4843a0636f3a}</Project> + <ReferenceOutputAssembly>false</ReferenceOutputAssembly> + </ProjectReference> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/modules/scinotes/src/c/scinotes.vcxproj.filters b/modules/scinotes/src/c/scinotes.vcxproj.filters new file mode 100755 index 000000000..f73b4a5f0 --- /dev/null +++ b/modules/scinotes/src/c/scinotes.vcxproj.filters @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <UniqueIdentifier>{efbdc4d1-dd8b-4ddb-bba6-47eddea3ea5c}</UniqueIdentifier> + <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions> + </Filter> + <Filter Include="Header Files"> + <UniqueIdentifier>{b70da001-658d-4f37-bf6f-a55067a0ee85}</UniqueIdentifier> + <Extensions>h;hpp;hxx;hm;inl</Extensions> + </Filter> + <Filter Include="localization"> + <UniqueIdentifier>{6ead0ade-2d54-423a-a14d-2b833c78e915}</UniqueIdentifier> + </Filter> + <Filter Include="Libraries Dependencies"> + <UniqueIdentifier>{6b10ec04-5b9e-47a0-b5d6-ca4858224eb5}</UniqueIdentifier> + </Filter> + <Filter Include="Libraries Dependencies\Imports"> + <UniqueIdentifier>{e68ea0f6-5f53-4216-800c-2243ad3d9e22}</UniqueIdentifier> + </Filter> + <Filter Include="swig"> + <UniqueIdentifier>{04789187-62f2-4df4-bb87-eb9fee2cb49a}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <UniqueIdentifier>{c470fad2-08f4-4f6d-a01c-ca6ca7bb4c80}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="..\cpp\callscinotes.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="DllmainSCINOTES.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\sci_gateway\c\gw_scinotes.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\sci_gateway\cpp\sci_closeSciNotesFromScilab.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\sci_gateway\cpp\sci_scinotes.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="ScilabKeywords.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\jni\ScilabKeywords_wrap.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\jni\SciNotes.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="..\..\includes\callscinotes.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\includes\dynlib_scinotes.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\includes\gw_scinotes.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="ScilabKeywords.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\jni\SciNotes.hxx"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <None Include="core_import.def"> + <Filter>Libraries Dependencies\Imports</Filter> + </None> + <None Include="..\jni\ScilabKeywords.i"> + <Filter>swig</Filter> + </None> + <None Include="..\..\Makefile.am" /> + <None Include="..\..\scinotes.iss" /> + <None Include="..\..\sci_gateway\scinotes_gateway.xml" /> + <None Include="..\..\locales\scinotes.pot"> + <Filter>localization</Filter> + </None> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="scinotes.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/modules/scinotes/src/cpp/.deps/.dirstamp b/modules/scinotes/src/cpp/.deps/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/cpp/.deps/.dirstamp diff --git a/modules/scinotes/src/cpp/.deps/libsciscinotes_algo_la-callscinotes.Plo b/modules/scinotes/src/cpp/.deps/libsciscinotes_algo_la-callscinotes.Plo new file mode 100755 index 000000000..c02d01f41 --- /dev/null +++ b/modules/scinotes/src/cpp/.deps/libsciscinotes_algo_la-callscinotes.Plo @@ -0,0 +1,379 @@ +src/cpp/libsciscinotes_algo_la-callscinotes.lo: src/cpp/callscinotes.cpp \ + /usr/include/stdc-predef.h src/jni/SciNotes.hxx \ + /usr/include/c++/5/iostream \ + /usr/include/x86_64-linux-gnu/c++/5/bits/c++config.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/cpu_defines.h \ + /usr/include/c++/5/ostream /usr/include/c++/5/ios \ + /usr/include/c++/5/iosfwd /usr/include/c++/5/bits/stringfwd.h \ + /usr/include/c++/5/bits/memoryfwd.h /usr/include/c++/5/bits/postypes.h \ + /usr/include/c++/5/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/bits/wchar2.h /usr/include/c++/5/exception \ + /usr/include/c++/5/bits/atomic_lockfree_defines.h \ + /usr/include/c++/5/bits/char_traits.h \ + /usr/include/c++/5/bits/stl_algobase.h \ + /usr/include/c++/5/bits/functexcept.h \ + /usr/include/c++/5/bits/exception_defines.h \ + /usr/include/c++/5/bits/cpp_type_traits.h \ + /usr/include/c++/5/ext/type_traits.h \ + /usr/include/c++/5/ext/numeric_traits.h \ + /usr/include/c++/5/bits/stl_pair.h /usr/include/c++/5/bits/move.h \ + /usr/include/c++/5/bits/concept_check.h \ + /usr/include/c++/5/bits/stl_iterator_base_types.h \ + /usr/include/c++/5/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/5/debug/debug.h /usr/include/c++/5/bits/stl_iterator.h \ + /usr/include/c++/5/bits/ptr_traits.h \ + /usr/include/c++/5/bits/predefined_ops.h \ + /usr/include/c++/5/bits/localefwd.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/c++locale.h \ + /usr/include/c++/5/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/5/cctype \ + /usr/include/ctype.h /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap-16.h \ + /usr/include/c++/5/bits/ios_base.h /usr/include/c++/5/ext/atomicity.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/gthr.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/timex.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/atomic_word.h \ + /usr/include/c++/5/bits/locale_classes.h /usr/include/c++/5/string \ + /usr/include/c++/5/bits/allocator.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h \ + /usr/include/c++/5/ext/new_allocator.h /usr/include/c++/5/new \ + /usr/include/c++/5/bits/ostream_insert.h \ + /usr/include/c++/5/bits/cxxabi_forced.h \ + /usr/include/c++/5/bits/stl_function.h \ + /usr/include/c++/5/backward/binders.h \ + /usr/include/c++/5/bits/range_access.h \ + /usr/include/c++/5/bits/basic_string.h \ + /usr/include/c++/5/ext/alloc_traits.h \ + /usr/include/c++/5/bits/basic_string.tcc \ + /usr/include/c++/5/bits/locale_classes.tcc /usr/include/c++/5/stdexcept \ + /usr/include/c++/5/streambuf /usr/include/c++/5/bits/streambuf.tcc \ + /usr/include/c++/5/bits/basic_ios.h \ + /usr/include/c++/5/bits/locale_facets.h /usr/include/c++/5/cwctype \ + /usr/include/wctype.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/ctype_base.h \ + /usr/include/c++/5/bits/streambuf_iterator.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/ctype_inline.h \ + /usr/include/c++/5/bits/locale_facets.tcc \ + /usr/include/c++/5/bits/basic_ios.tcc \ + /usr/include/c++/5/bits/ostream.tcc /usr/include/c++/5/istream \ + /usr/include/c++/5/bits/istream.tcc /usr/include/string.h \ + /usr/include/x86_64-linux-gnu/bits/string3.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/select2.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-float.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib.h \ + /usr/lib/jvm/java-8-openjdk-amd64/include/jni.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ + /usr/include/x86_64-linux-gnu/bits/stdio.h \ + /usr/include/x86_64-linux-gnu/bits/stdio2.h \ + /usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h \ + ../../modules/commons/src/jni/GiwsException.hxx includes/callscinotes.h \ + includes/dynlib_scinotes.h \ + ../../modules/localization/includes/charEncoding.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h \ + ../../modules/core/includes/MALLOC.h \ + ../../modules/core/includes/sci_mem_alloc.h \ + ../../modules/core/includes/BOOL.h \ + ../../modules/jvm/includes/getScilabJavaVM.h \ + ../../modules/core/includes/freeArrayOfString.h \ + ../../modules/core/includes/BOOL.h \ + ../../modules/fileio/includes/getFullFilename.h \ + ../../modules/fileio/includes/dynlib_fileio.h + +/usr/include/stdc-predef.h: + +src/jni/SciNotes.hxx: + +/usr/include/c++/5/iostream: + +/usr/include/x86_64-linux-gnu/c++/5/bits/c++config.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/cpu_defines.h: + +/usr/include/c++/5/ostream: + +/usr/include/c++/5/ios: + +/usr/include/c++/5/iosfwd: + +/usr/include/c++/5/bits/stringfwd.h: + +/usr/include/c++/5/bits/memoryfwd.h: + +/usr/include/c++/5/bits/postypes.h: + +/usr/include/c++/5/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/bits/wchar2.h: + +/usr/include/c++/5/exception: + +/usr/include/c++/5/bits/atomic_lockfree_defines.h: + +/usr/include/c++/5/bits/char_traits.h: + +/usr/include/c++/5/bits/stl_algobase.h: + +/usr/include/c++/5/bits/functexcept.h: + +/usr/include/c++/5/bits/exception_defines.h: + +/usr/include/c++/5/bits/cpp_type_traits.h: + +/usr/include/c++/5/ext/type_traits.h: + +/usr/include/c++/5/ext/numeric_traits.h: + +/usr/include/c++/5/bits/stl_pair.h: + +/usr/include/c++/5/bits/move.h: + +/usr/include/c++/5/bits/concept_check.h: + +/usr/include/c++/5/bits/stl_iterator_base_types.h: + +/usr/include/c++/5/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/5/debug/debug.h: + +/usr/include/c++/5/bits/stl_iterator.h: + +/usr/include/c++/5/bits/ptr_traits.h: + +/usr/include/c++/5/bits/predefined_ops.h: + +/usr/include/c++/5/bits/localefwd.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/c++locale.h: + +/usr/include/c++/5/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/5/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: + +/usr/include/c++/5/bits/ios_base.h: + +/usr/include/c++/5/ext/atomicity.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/gthr.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/timex.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/atomic_word.h: + +/usr/include/c++/5/bits/locale_classes.h: + +/usr/include/c++/5/string: + +/usr/include/c++/5/bits/allocator.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h: + +/usr/include/c++/5/ext/new_allocator.h: + +/usr/include/c++/5/new: + +/usr/include/c++/5/bits/ostream_insert.h: + +/usr/include/c++/5/bits/cxxabi_forced.h: + +/usr/include/c++/5/bits/stl_function.h: + +/usr/include/c++/5/backward/binders.h: + +/usr/include/c++/5/bits/range_access.h: + +/usr/include/c++/5/bits/basic_string.h: + +/usr/include/c++/5/ext/alloc_traits.h: + +/usr/include/c++/5/bits/basic_string.tcc: + +/usr/include/c++/5/bits/locale_classes.tcc: + +/usr/include/c++/5/stdexcept: + +/usr/include/c++/5/streambuf: + +/usr/include/c++/5/bits/streambuf.tcc: + +/usr/include/c++/5/bits/basic_ios.h: + +/usr/include/c++/5/bits/locale_facets.h: + +/usr/include/c++/5/cwctype: + +/usr/include/wctype.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/ctype_base.h: + +/usr/include/c++/5/bits/streambuf_iterator.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/ctype_inline.h: + +/usr/include/c++/5/bits/locale_facets.tcc: + +/usr/include/c++/5/bits/basic_ios.tcc: + +/usr/include/c++/5/bits/ostream.tcc: + +/usr/include/c++/5/istream: + +/usr/include/c++/5/bits/istream.tcc: + +/usr/include/string.h: + +/usr/include/x86_64-linux-gnu/bits/string3.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/select2.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib.h: + +/usr/lib/jvm/java-8-openjdk-amd64/include/jni.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/x86_64-linux-gnu/bits/stdio.h: + +/usr/include/x86_64-linux-gnu/bits/stdio2.h: + +/usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h: + +../../modules/commons/src/jni/GiwsException.hxx: + +includes/callscinotes.h: + +includes/dynlib_scinotes.h: + +../../modules/localization/includes/charEncoding.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +../../modules/core/includes/MALLOC.h: + +../../modules/core/includes/sci_mem_alloc.h: + +../../modules/core/includes/BOOL.h: + +../../modules/jvm/includes/getScilabJavaVM.h: + +../../modules/core/includes/freeArrayOfString.h: + +../../modules/core/includes/BOOL.h: + +../../modules/fileio/includes/getFullFilename.h: + +../../modules/fileio/includes/dynlib_fileio.h: diff --git a/modules/scinotes/src/cpp/.dirstamp b/modules/scinotes/src/cpp/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/cpp/.dirstamp diff --git a/modules/scinotes/src/cpp/.libs/libsciscinotes_algo_la-callscinotes.o b/modules/scinotes/src/cpp/.libs/libsciscinotes_algo_la-callscinotes.o Binary files differnew file mode 100755 index 000000000..3411e98be --- /dev/null +++ b/modules/scinotes/src/cpp/.libs/libsciscinotes_algo_la-callscinotes.o diff --git a/modules/scinotes/src/cpp/callscinotes.cpp b/modules/scinotes/src/cpp/callscinotes.cpp new file mode 100755 index 000000000..5a4a7faa8 --- /dev/null +++ b/modules/scinotes/src/cpp/callscinotes.cpp @@ -0,0 +1,137 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +#include "SciNotes.hxx" + +extern "C" +{ +#include "callscinotes.h" +#include "charEncoding.h" +#include "getScilabJavaVM.h" +#include "charEncoding.h" +#include "MALLOC.h" +#include "freeArrayOfString.h" +#include "getFullFilename.h" +} +/*--------------------------------------------------------------------------*/ +using namespace org_scilab_modules_scinotes; +/*--------------------------------------------------------------------------*/ +int callSciNotesW(wchar_t **_wcfilenames, int _nbfiles) +{ + if ( (_wcfilenames) && (_nbfiles > 0) ) + { + int i = 0; + for (i = 0; i < _nbfiles; i++) + { + if (_wcfilenames[i]) + { + wchar_t *wcFullFilename = getFullFilenameW(_wcfilenames[i]); + if (wcFullFilename) + { + char *fullFilename = wide_string_to_UTF8(wcFullFilename); + if (fullFilename) + { + SciNotes::scinotes(getScilabJavaVM(), fullFilename); + FREE(fullFilename); + fullFilename = NULL; + } + + FREE(wcFullFilename); + wcFullFilename = NULL; + } + } + } + } + else + { + SciNotes::scinotes(getScilabJavaVM()); + } + return 0; +} + +int callSciNotesWWithLineNumberAndFunction(wchar_t **_wcfilenames, double* pdblLineNumber, char *functionName, int _nbfiles) +{ + if ( (_wcfilenames) && (_nbfiles > 0) ) + { + int i = 0; + for (i = 0; i < _nbfiles; i++) + { + if (_wcfilenames[i]) + { + wchar_t *wcFullFilename = getFullFilenameW(_wcfilenames[i]); + if (wcFullFilename) + { + char *fullFilename = wide_string_to_UTF8(wcFullFilename); + if (fullFilename) + { + SciNotes::scinotes(getScilabJavaVM(), fullFilename, (int)pdblLineNumber[i], functionName); + FREE(fullFilename); + fullFilename = NULL; + } + + FREE(wcFullFilename); + wcFullFilename = NULL; + } + } + } + } + else + { + SciNotes::scinotes(getScilabJavaVM()); + } + return 0; +} + +int callSciNotesWWithOption(wchar_t **_wcfilenames, wchar_t** option, int _nboptions, int _nbfiles) +{ + if ( (_wcfilenames) && (_nbfiles > 0) ) + { + int i = 0; + char ** opt = NULL; + if (_nboptions) + { + opt = new char*[_nboptions]; + for (int i = 0; i < _nboptions; i++) + { + opt[i] = wide_string_to_UTF8(option[i]); + } + } + + for (i = 0; i < _nbfiles; i++) + { + if (_wcfilenames[i]) + { + wchar_t *wcFullFilename = getFullFilenameW(_wcfilenames[i]); + if (wcFullFilename) + { + char *fullFilename = wide_string_to_UTF8(wcFullFilename); + if (fullFilename) + { + SciNotes::scinotes(getScilabJavaVM(), fullFilename, opt, _nboptions); + FREE(fullFilename); + fullFilename = NULL; + } + + FREE(wcFullFilename); + wcFullFilename = NULL; + } + } + } + FREE(opt); + } + else + { + SciNotes::scinotes(getScilabJavaVM()); + } + return 0; +} +/*--------------------------------------------------------------------------*/ diff --git a/modules/scinotes/src/cpp/libsciscinotes_algo_la-callscinotes.lo b/modules/scinotes/src/cpp/libsciscinotes_algo_la-callscinotes.lo new file mode 100755 index 000000000..1a75da516 --- /dev/null +++ b/modules/scinotes/src/cpp/libsciscinotes_algo_la-callscinotes.lo @@ -0,0 +1,12 @@ +# src/cpp/libsciscinotes_algo_la-callscinotes.lo - a libtool object file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/libsciscinotes_algo_la-callscinotes.o' + +# Name of the non-PIC object +non_pic_object=none + diff --git a/modules/scinotes/src/java/jflex/function.jflex b/modules/scinotes/src/java/jflex/function.jflex new file mode 100755 index 000000000..02118f4d6 --- /dev/null +++ b/modules/scinotes/src/java/jflex/function.jflex @@ -0,0 +1,258 @@ +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import javax.swing.text.Element; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") +%% + +%public +%class FunctionScanner +%final +%unicode +%char +%type int + +%switch + +%{ + List<String> returnValues; + List<String> argsValues; + String functionName; + int end; + + private ScilabDocument doc; + private String id; + private boolean inRETS; + + public FunctionScanner(ScilabDocument doc) { + this.doc = doc; + returnValues = new ArrayList(); + argsValues = new ArrayList(); + } + + public String getFunctionName() { + return functionName; + } + + public List<String> getReturnValues() { + return returnValues; + } + + public List<String> getArgsValues() { + return argsValues; + } + + public int getLineType(int p0, int p1) { + try { + returnValues = new ArrayList(); + argsValues = new ArrayList(); + end = p1; + yyreset(new ScilabDocumentReader(doc, p0, p1)); + yybegin(BROKEN); + int broken = yylex(); + + yyreset(new ScilabDocumentReader(doc, p0, p1)); + while (true) { + int ret = yylex(); + if (ret != ScilabDocument.ScilabLeafElement.BROKEN) { + return ret | broken; + } + Element elem = doc.getDefaultRootElement(); + int start = end + 1; + elem = elem.getElement(elem.getElementIndex(end + 1)); + end = elem.getEndOffset(); + yyreset(new ScilabDocumentReader(doc, elem.getStartOffset(), end)); + if (inRETS) { + inRETS = false; + yybegin(RETS); + } else { + yybegin(ARGS); + } + } + } catch (IOException e) { + return ScilabDocument.ScilabLeafElement.NOTHING; + } + } + + public FunctionInfo getFunctionInfo() { + return new FunctionInfo(functionName, returnValues, argsValues); + } + + public class FunctionInfo { + public String functionName; + public List<String> returnValues; + public List<String> argsValues; + + public FunctionInfo(String name, List ret, List args) { + this.functionName = name; + this.returnValues = ret; + this.argsValues = args; + } + } +%} + +%eofval{ + return ScilabDocument.ScilabLeafElement.NOTHING; +%eofval} + +/* main character classes */ +white = [ \t]+ +eol = \n + +comments = ("//".*)?{eol} +break = ".."(".")*{white}*{comments} + +brokenline = ([^\.]* | ([^\.]*"."[^\.]+)+){break} + +id = [a-zA-Z%_#!$?][a-zA-Z0-9_#!$?]* +spec = [^a-zA-Z0-9_#!$?] + +equal = {white}* "=" {white}* + +rpar = ")"[,; \t]*{comments} + +fun = {white}* "function" {white} +funb = {white}* "function[" +endfun = {white}* "endfunction" {spec} + +%x FUNCTION, TYPEID, FUNNAME, RETS, ARGS, BROKEN + +%% + +<YYINITIAL> { + {funb} { + yybegin(RETS); + } + + {fun} { + yybegin(FUNCTION); + } + + {endfun} { + return ScilabDocument.ScilabLeafElement.ENDFUN; + } + + . | + {eol} { + return ScilabDocument.ScilabLeafElement.NOTHING; + } +} + +<BROKEN> { + {brokenline} { + return ScilabDocument.ScilabLeafElement.BROKEN; + } + + . | + {eol} { + return 0; + } +} + +<FUNCTION> { + "[" { + yybegin(RETS); + } + + {id} { + id = yytext(); + yybegin(TYPEID); + } + + . | + {eol} { + return ScilabDocument.ScilabLeafElement.NOTHING; + } +} + +<TYPEID> { + {equal} { + returnValues.add(id); + yybegin(FUNNAME); + } + + "(" { + functionName = id; + yybegin(ARGS); + } + + {white} { } + + {comments} { + functionName = id; + return ScilabDocument.ScilabLeafElement.FUN; + } + + . { + return ScilabDocument.ScilabLeafElement.NOTHING; + } +} + +<FUNNAME> { + {id} { + functionName = yytext(); + } + + [ \t]*"(" { + yybegin(ARGS); + } + + {comments} { + return ScilabDocument.ScilabLeafElement.FUN; + } + + . { + return ScilabDocument.ScilabLeafElement.NOTHING; + } +} + +<RETS> { + {id} { + returnValues.add(yytext()); + } + + "," | + {white} { } + + "]"{equal} { + yybegin(FUNNAME); + } + + {break} { + inRETS = true; + return ScilabDocument.ScilabLeafElement.BROKEN; + } + + . | + {eol} { + return ScilabDocument.ScilabLeafElement.NOTHING; + } +} + +<ARGS> { + {id} { + argsValues.add(yytext()); + } + + "," | + {white} { } + + {break} { + return ScilabDocument.ScilabLeafElement.BROKEN; + } + + {rpar} { + return ScilabDocument.ScilabLeafElement.FUN; + } + + . | + {eol} { + return ScilabDocument.ScilabLeafElement.NOTHING; + } +} diff --git a/modules/scinotes/src/java/jflex/indentation.jflex b/modules/scinotes/src/java/jflex/indentation.jflex new file mode 100755 index 000000000..d99972ca9 --- /dev/null +++ b/modules/scinotes/src/java/jflex/indentation.jflex @@ -0,0 +1,196 @@ +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.io.IOException; +import javax.swing.text.Element; +import javax.swing.text.BadLocationException; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") +%% + +%public +%class IndentScanner +%final +%unicode +%char +%type int + +%switch + +%{ + private ScilabDocument doc; + private Element elem; + + public IndentScanner(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + } + + public int getIndentNumber(int lineNumber, char type) { + if (lineNumber < 0) { + return 0; + } + try { + Element line = elem.getElement(lineNumber); + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + yyreset(new ScilabDocumentReader(doc, startL, endL)); + switch (type) { + case ' ': + yybegin(WHITE); + break; + case '\t': + yybegin(TAB); + break; + default: + yybegin(WHITE); + } + return yylex(); + } catch (IOException e) { + return 0; + } + } + + public int getTabsAtBeginning(int pos) { + Element line = elem.getElement(pos); + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + try { + yyreset(new ScilabDocumentReader(doc, startL, endL)); + yybegin(BEG); + if (yylex() == 1) { + return yylength(); + } + } catch (IOException e) { + return 0; + } + return 0; + } + + public void getIndentLevel(int pos, int[] level) { + Element line = elem.getElement(elem.getElementIndex(pos)); + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + level[0] = 0; + level[1] = 0; + try { + yyreset(new ScilabDocumentReader(doc, startL, endL)); + yybegin(INDENT); + do { + switch (yylex()) { + case 0: + break; + case 1: + level[1]++; + break; + case 2: + if (level[1] > 0) { + level[1]--; + } else { + level[0]++; + } + break; + case 3: + if (level[1] == 0) { + level[0]++; + level[1]++; + } + } + } while (zzMarkedPos != 0); + } catch (IOException e) { } + } +%} + +%eofval{ + return 0; +%eofval} + +/* main character classes */ + +eol = \n + +comment = "//".*{eol} + +spec = [a-zA-Z0-9%_#!$?0-9] + +string = (([^\'\"\r\n]*)|([\'\"]{2}))+ +qstring = (\"|\'){string}(\"|\') +transp = ({spec} | ")" | "]" | "}") "'" + +indentP = ("function" | "if" | "for" | "while" | "try" | "select") +indentPx = {indentP}{spec}+ +xindentP = {spec}{indentP} + +indentM = ("endfunction" | "end") +indentMx = {indentM}{spec}+ +xindentM = {spec}{indentM} +indentMP = ("else" | "elseif" | "catch" | "case") +indentMPx = {indentMP}{spec}+ +xindentMP = {spec}{indentMP} + +%x INDENT, WHITE, TAB, BEG + +%% + +<INDENT> { + {transp} | + {comment} | + {indentPx} | + {qstring} { } + + {indentP} { + return 1; + } + + {indentM} { + return 2; + } + + {indentMP} { + return 3; + } + + . | + {xindentP} | + {xindentM} | + {xindentMP} | + {indentMPx} | + {indentMx} { } + + {eol} { + return 0; + } +} + +<WHITE> { + " "* { + return yylength(); + } + + . | + {eol} { + return 0; + } +} + +<TAB> { + "\t"* { + return yylength(); + } + + . | + {eol} { + return 0; + } +} + +<BEG> { + ^[ \t]+ { + return 1; + } + + . | + {eol} { } +}
\ No newline at end of file diff --git a/modules/scinotes/src/java/jflex/matchingblock.jflex b/modules/scinotes/src/java/jflex/matchingblock.jflex new file mode 100755 index 000000000..cdfec5554 --- /dev/null +++ b/modules/scinotes/src/java/jflex/matchingblock.jflex @@ -0,0 +1,286 @@ +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.io.IOException; +import javax.swing.text.Element; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") +%% + +%public +%class MatchingBlockScanner +%final +%unicode +%char +%type int +%buffer 256 + +%switch + +%{ + private ScilabDocument doc; + private Element elem; + private boolean transp = false; + private ScilabLexer scilabLexer; + private int start; + private int end; + private int savePos; + + public MatchingBlockScanner(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + this.scilabLexer = doc.createLexer(); + } + + public MatchingPositions getNextBlock(int pos, boolean lr) { + int s = 1; + transp = false; + try { + if (lr) { + start = pos; + end = doc.getEndPosition().getOffset(); + yyreset(new ScilabDocumentReader(doc, start, end)); + yybegin(LR); + } else { + start = pos - 1; + end = 0; + yyreset(new ScilabDocumentReader(doc, true, start, end)); + yybegin(RL); + } + do { + if (yylex() == 0) { + s--; + } else { + s++; + } + } while (zzMarkedPos != 0 && s != 0); + } catch (IOException e) { + return null; + } + if (s == 0) { + if (lr) { + return new MatchingPositions(pos, pos, pos + yychar, pos + yychar + (transp?(yylength()-1):yylength())); + } else { + return new MatchingPositions(pos, pos, pos - yychar - yylength(), pos - yychar); + } + } + + return null; + } + + public MatchingPositions getMatchingBlock(int pos, boolean lr) { + int p1, s = 1; + transp = false; + try { + if (lr) { + start = pos; + end = doc.getEndPosition().getOffset(); + yyreset(new ScilabDocumentReader(doc, start, end)); + yybegin(OPENCLOSE); + if (yylex() != 1) { + return null; + } + + p1 = pos + yylength(); + yybegin(LR); + } else { + start = pos - 1; + end = 0; + yyreset(new ScilabDocumentReader(doc, true, start, end)); + yybegin(CLOSEOPEN); + if (yylex() != 1) { + return null; + } + p1 = pos - yylength(); + yybegin(RL); + } + + do { + if (yylex() == 0) { + s--; + } else { + s++; + } + } while (zzMarkedPos != 0 && s != 0); + } catch (IOException e) { + return null; + } + if (s == 0) { + if (lr) { + return new MatchingPositions(pos, p1, pos + yychar, pos + yychar + (transp?(yylength()-1):yylength())); + } else { + return new MatchingPositions(p1, pos, pos - yychar - yylength(), pos - yychar); + } + } + + return null; + } + + public final class MatchingPositions { + public int firstB; + public int firstE; + public int secondB; + public int secondE; + + private MatchingPositions(int x1, int x2, int y1, int y2) { + firstB = x1; + firstE = x2; + secondB = y1; + secondE = y2; + } + } +%} + +%eofval{ + return -1; +%eofval} + +/* main character classes */ +eol = \n + +comment = "//".*{eol} + +tnemmoc = {eol}([^\r\n]*"//")+ + +spec = [a-zA-Z0-9_#!$?] + +id = [a-zA-Z%_#!?][a-zA-Z0-9_#!$?]* + +string = (([^\'\"\r\n]*)|([\'\"]{2}))* +qstring = (\"|\'){string}(\"|\') +gnirtsq = \"{string}(\"|\') +transp = ({spec} | ")" | "]" | "}") "'" + +openK = ("if" | "for" | "while" | "select" | "try" | "function") +openKx = {openK}{spec}+ + +elseif = "elseif" | "else" + +openS = "(" | "[" | "{" +closeK = ("end" | "endfunction") +closeKx = {closeK}{spec}+ +xcloseK = ({spec} | "%" ){closeK} +closeS = ")" | "]" | "}" + +esolcK = ("fi" | "rof" | "elihw" | "tceles" | "yrt" | "noitcnuf") +esolcKx = {spec}{esolcK} +xesolcK = {esolcK}{spec} +nepoK = ("dne" | "noitcnufdne") +nepoKx = {spec}{nepoK} + +%x LR, RL, OPENCLOSE, CLOSEOPEN, PSNART, SPEC + +%% + +<LR> { + {transp} { + char c = yycharat(yylength() - 2); + if (c == ')' || c == ']' || c == '}') { + transp = true; + return 0; + } + } + + "elseif" | + {comment} | + {openKx} | + {qstring} { } + + {openS} | + {openK} { + return 1; + } + + {closeS} | + {closeK} { + return 0; + } + + {id} | + {closeKx} | + {xcloseK} | + . | + {eol} { } +} + +<RL> { + \' { + yypushback(1); + yybegin(PSNART); + } + + "fiesle" | + {tnemmoc} | + {esolcKx} | + {xesolcK} | + {gnirtsq} { } + + {closeS} | + {nepoK} { + return 1; + } + + {openS} | + {esolcK} { + return 0; + } + + {nepoKx} | + . | + {eol} { } +} + +<PSNART> { + \' { + if (scilabLexer.getKeyword(start - yychar, false) == ScilabLexerConstants.STRING) { + savePos = start - yychar - scilabLexer.beginString - scilabLexer.start; + yybegin(SPEC); + } else { + yybegin(RL); + } + } +} + +<SPEC> { + . | + {eol} { + if (--savePos == 0) { + yybegin(RL); + } + } +} + +<OPENCLOSE> { + {openKx} { + return 0; + } + + {elseif} | + {openS} | + {openK} { + return 1; + } + + . | + {eol} { + return 0; + } +} + +<CLOSEOPEN> { + {nepoKx} { + return 0; + } + + {closeS} | + {nepoK} { + return 1; + } + + . | + {eol} { + return 0; + } +} diff --git a/modules/scinotes/src/java/jflex/scilab.jflex b/modules/scinotes/src/java/jflex/scilab.jflex new file mode 100755 index 000000000..5ece120cb --- /dev/null +++ b/modules/scinotes/src/java/jflex/scilab.jflex @@ -0,0 +1,557 @@ +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.io.IOException; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.commons.ScilabCommonsUtils; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") + +%% + +%public +%class ScilabLexer +%extends ScilabLexerConstants +%final +%unicode +%char +%type int +%switch +%pack + +%{ + public int start; + public int end; + public int beginString; + public static Set<String> commands = new HashSet<String>(); + public static Set<String> macros = new HashSet<String>(); + public static Set<String> variables = new HashSet<String>(); + public Set<String> infile; + + private ScilabDocument doc; + private boolean transposable; + private Element elem; + private boolean breakstring; + + static { + // For SciNotes colors in preferences + commands.add("cos"); + macros.add("cosh"); + } + + public ScilabLexer(ScilabDocument doc) { + this(doc, true); + } + + public ScilabLexer(ScilabDocument doc, boolean update) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + this.infile = doc.getFunctionsInDoc(); + if (update) { + update(); + } + } + + public static void update() { + if (ScilabCommonsUtils.isScilabThread()) { + String[] vars = ScilabKeywords.GetVariablesName(); + String[] funs = ScilabKeywords.GetFunctionsName(); + String[] macs = ScilabKeywords.GetMacrosName(); + variables.clear(); + commands.clear(); + macros.clear(); + if (vars != null) { + variables.addAll(Arrays.asList(vars)); + } + if (funs != null) { + commands.addAll(Arrays.asList(funs)); + } + if (macs != null) { + macros.addAll(Arrays.asList(macs)); + } + } + } + + public void setRange(int p0, int p1) { + start = p0; + end = p1; + transposable = false; + breakstring = false; + yyreset(new ScilabDocumentReader(doc, p0, p1)); + int currentLine = elem.getElementIndex(start); + if (currentLine != 0 && ((ScilabDocument.ScilabLeafElement) elem.getElement(currentLine - 1)).isBrokenString()) { + yybegin(QSTRING); + } + } + + public int yychar() { + return yychar; + } + + public int scan() throws IOException { + int ret = yylex(); + if (start + yychar + yylength() == end - 1) { + ((ScilabDocument.ScilabLeafElement) elem.getElement(elem.getElementIndex(start))).setBrokenString(breakstring); + breakstring = false; + } + return ret; + } + + public int getKeyword(int pos, boolean strict) { + Element line = elem.getElement(elem.getElementIndex(pos)); + int end = line.getEndOffset(); + int tok = -1; + start = line.getStartOffset(); + int startL = start; + int s = -1; + + try { + yyreset(new ScilabDocumentReader(doc, start, end)); + if (!strict) { + pos++; + } + + while (startL < pos && (s != startL || yystate() == BREAKSTRING)) { + s = startL; + tok = yylex(); + startL = start + yychar + yylength(); + } + + return tok; + } catch (IOException e) { + return ScilabLexerConstants.DEFAULT; + } + } + + public static ScilabTokens getScilabTokens(String str) { + ScilabDocument doc = new ScilabDocument(false); + try { + doc.insertString(0, str, null); + } catch (BadLocationException e) { } + return getScilabTokens(doc); + } + + public static ScilabTokens getScilabTokens(ScilabDocument doc) { + ScilabLexer lexer = new ScilabLexer(doc); + lexer.yyreset(new ScilabDocumentReader(doc, 0, doc.getLength())); + ScilabTokens tokens = new ScilabTokens(); + int tok = -1; + try { + while (tok != ScilabLexerConstants.EOF) { + tok = lexer.yylex(); + tokens.add(tok, lexer.yychar + lexer.yylength()); + } + } catch (IOException e) { } + + return tokens; + } + + public static class ScilabTokens { + private List<Integer> tokenType = new ArrayList<Integer>(); + private List<Integer> tokenPos = new ArrayList<Integer>(); + + ScilabTokens() { } + + void add(final int type, final int pos) { + tokenType.add(type); + tokenPos.add(pos); + } + + public final List<Integer> getTokenType() { + return tokenType; + } + + public final List<Integer> getTokenPos() { + return tokenPos; + } + } +%} + +/* main character classes */ +eol = \n + +open = "[" | "(" | "{" +close = "]" | ")" | "}" + +comment = "//" + +quote = "'" + +dquote = "\"" + +cstes = "%t" | "%T" | "%f" | "%F" | "%e" | "%pi" | "%inf" | "%i" | "%z" | "%s" | "%nan" | "%eps" | "SCI" | "WSCI" | "SCIHOME" | "TMPDIR" + +operator = ".'" | ".*" | "./" | ".\\" | ".^" | ".**" | "+" | "-" | "/" | "\\" | "*" | "^" | "**" | "==" | "~=" | "<>" | "<" | ">" | "<=" | ">=" | ".*." | "./." | ".\\." | "/." | "=" | "&" | "|" | "@" | "@=" | "~" + +functionKwds = "function" | "endfunction" + +structureKwds = "then" | "do" | "catch" | "case" + +elseif = "elseif" | "else" + +openCloseStructureKwds = "if" | "for" | "while" | "try" | "select" | "end" + +controlKwds = "abort" | "break" | "quit" | "return" | "resume" | "pause" | "continue" | "exit" + +authors = "Calixte Denizet" | "Calixte DENIZET" | "Sylvestre Ledru" | "Sylvestre LEDRU" | "Antoine Elias" | "Antoine ELIAS" | "Bruno Jofret" | "Bruno JOFRET" | "Claude Gomez" | "Claude GOMEZ" | "Clement David" | "Clement DAVID" | "Manuel Juliachs" | "Manuel JULIACHS" | "Sheldon Cooper" | "Leonard Hofstadter" | "Serge Steer" | "Serge STEER" | "Vincent Couvert" | "Vincent COUVERT" | "Adeline Carnis" | "Adeline CARNIS" | "Charlotte Hecquet" | "Charlotte HECQUET" | "Paul Bignier" | "Paul BIGNIER" | "Alexandre Herisse" | "Alexandre HERISSE" | "Simon Marchetto" | "Simon MARCHETTO" | "Vladislav Trubkin" | "Vladislav TRUBKIN" | "Cedric Delamarre" | "Cedric DELAMARRE" | "Inria" | "INRIA" | "DIGITEO" | "Digiteo" | "Scilab Enterprises" | "ENPC" + +error = "Scilab Entreprises" | "Scilab Entreprise" | "Scilab Enterprise" +todo = ("TODO" | "todo" | "Todo")[ \t]*:[^\n]* + +break = ".."(".")* +breakinstring = {break}[ \t]*({comment} | {eol}) + +special = "$" | ":" | {break} + +string = (([^ \t\'\"\r\n\.]*)|([\'\"]{2}))+ + +id = ([a-zA-Z%_#!?][a-zA-Z0-9_#!$?]*)|("$"[a-zA-Z0-9_#!$?]+) + +badid = ([0-9$][a-zA-Z0-9_#!$?]+) +whitabs = (" "+"\t" | "\t"+" ")[ \t]* +badop = [+-]([\*\/\\\^] | "."[\*\+\-\/\\\^]) | ":=" | "->" | ("="[ \t]*">") | ("="[ \t]*"<") | " !=" | "&&" | "||" | ([*+-/\\\^]"=") + +dot = "." + +url = ("http://"|"https://"|"ftp://"|"dav://"|"davs://"|"sftp://"|"ftps://"|"smb:///"|"file://")[^ \t\f\n\r\'\"]+ +mailaddr = [ \t]*[a-zA-Z0-9_\.\-]+"@"([a-zA-Z0-9\-]+".")+[a-zA-Z]{2,5}[ \t]* +mail = ("<" {mailaddr} ">") | ("mailto:" {mailaddr}) + +latex = "$$"(([^$]*|"\\$")+)"$$" +latexinstring = (\"|\')"$"(([^$\'\"]*|"\\$"|([\'\"]{2}))+)"$"(\"|\') + +digit = [0-9] +exp = [dDeE][+-]?{digit}* +number = ({digit}+"."?{digit}*{exp}?)|("."{digit}+{exp}?) + +arabic_char = [\u0600-\u06FF\u0750-\u077F\uFB50-\uFDFF\uFE70-\uFEFF] +hebrew_char = [\u0590-\u05FF\uFB1D-\uFB4F] +nko_char = [\u07C0-\u07FF] +thaana_char = [\u0780-\u07BF] +rtl_char = {arabic_char}|{hebrew_char}|{nko_char}|{thaana_char} +rtl_comment = {rtl_char}[^\n]* +rtl_in_string = {rtl_char}(([^\'\"\r\n\.]*)|([\'\"]{2}))+ + +%x QSTRING, COMMENT, FIELD, COMMANDS, COMMANDSWHITE, BREAKSTRING + +%% + +<YYINITIAL> { + {comment} { + transposable = false; + yypushback(2); + yybegin(COMMENT); + } + + {operator} { + transposable = false; + return ScilabLexerConstants.OPERATOR; + } + + {functionKwds} { + transposable = false; + return ScilabLexerConstants.FKEYWORD; + } + + {openCloseStructureKwds} { + transposable = false; + return ScilabLexerConstants.OSKEYWORD; + } + + {structureKwds} { + transposable = false; + return ScilabLexerConstants.SKEYWORD; + } + + {elseif} { + transposable = false; + return ScilabLexerConstants.ELSEIF; + } + + {controlKwds} { + transposable = false; + return ScilabLexerConstants.CKEYWORD; + } + + {cstes} { + transposable = true; + return ScilabLexerConstants.CONSTANTES; + } + + {id} { + transposable = true; + String str = yytext(); + if (commands.contains(str)) { + yybegin(COMMANDS); + return ScilabLexerConstants.COMMANDS; + } else if (macros.contains(str)) { + yybegin(COMMANDS); + return ScilabLexerConstants.MACROS; + } else if (infile.contains(str)) { + yybegin(COMMANDS); + return ScilabLexerConstants.MACROINFILE; + } else { + List<String>[] arr = doc.getInOutArgs(start + yychar); + if (arr != null && (arr[0].contains(str) || arr[1].contains(str))) { + return ScilabLexerConstants.INPUTOUTPUTARGS; + } else if (variables.contains(str)) { + return ScilabLexerConstants.VARIABLES; + } + } + return ScilabLexerConstants.ID; + } + + {number} { + transposable = true; + return ScilabLexerConstants.NUMBER; + } + + {special} { + transposable = false; + return ScilabLexerConstants.SPECIAL; + } + + {dot} { + transposable = false; + yybegin(FIELD); + return ScilabLexerConstants.OPERATOR; + } + + {latexinstring} { + return ScilabLexerConstants.LATEXINSTRING; + } + + {quote} { + if (transposable) { + return ScilabLexerConstants.TRANSP; + } else { + beginString = zzStartRead; + yybegin(QSTRING); + return ScilabLexerConstants.STRING; + } + } + + {open} { + transposable = false; + return ScilabLexerConstants.OPENCLOSE; + } + + {close} { + transposable = true; + return ScilabLexerConstants.OPENCLOSE; + } + + {dquote} { + transposable = false; + beginString = zzStartRead; + yybegin(QSTRING); + return ScilabLexerConstants.STRING; + } + + {badid} | + {badop} | + {whitabs} { + return ScilabLexerConstants.ERROR; + } + + " " { + transposable = false; + return ScilabLexerConstants.WHITE; + } + + "\t" { + transposable = false; + return ScilabLexerConstants.TAB; + } + + . | + {eol} { + transposable = false; + return ScilabLexerConstants.DEFAULT; + } +} + +<COMMANDS> { + [ \t]*"(" { + yypushback(yylength()); + yybegin(YYINITIAL); + } + + " " { + yybegin(COMMANDSWHITE); + return ScilabLexerConstants.WHITE; + } + + "\t" { + yybegin(COMMANDSWHITE); + return ScilabLexerConstants.TAB; + } + . + { + yypushback(1); + yybegin(YYINITIAL); + } + + {eol} { } +} + +<COMMANDSWHITE> { + {comment} { + transposable = false; + yypushback(2); + yybegin(COMMENT); + } + + ([^ \t,;/]*) | ("/"[^ /]*) { + return ScilabLexerConstants.STRING; + } + + " " { + return ScilabLexerConstants.WHITE; + } + + "\t" { + return ScilabLexerConstants.TAB; + } + + . | + {eol} { + yypushback(1); + yybegin(YYINITIAL); + } +} + +<FIELD> { + {id} { + transposable = true; + return ScilabLexerConstants.FIELD; + } + + . | + {eol} { + yypushback(1); + yybegin(YYINITIAL); + } +} + +<QSTRING> { + {breakinstring} { + yypushback(yylength()); + yybegin(BREAKSTRING); + transposable = false; + return ScilabLexerConstants.STRING; + } + + " " { + return ScilabLexerConstants.WHITE_STRING; + } + + "\t" { + return ScilabLexerConstants.TAB_STRING; + } + + {rtl_in_string} | + {string} | + "." { + return ScilabLexerConstants.STRING; + } + + (\'|\") { + transposable = false; + yybegin(YYINITIAL); + return ScilabLexerConstants.STRING; + } + + . | + {eol} { + return ScilabLexerConstants.DEFAULT; + } +} + +<COMMENT> { + {todo} { + return ScilabLexerConstants.TODO; + } + + {error} { + return ScilabLexerConstants.ERROR; + } + + + {authors} { + return ScilabLexerConstants.AUTHORS; + } + + {url} { + return ScilabLexerConstants.URL; + } + + {mail} { + return ScilabLexerConstants.MAIL; + } + + {latex} { + return ScilabLexerConstants.LATEX; + } + + " " { + return ScilabLexerConstants.WHITE_COMMENT; + } + + "\t" { + return ScilabLexerConstants.TAB_COMMENT; + } + + {rtl_comment} { + return ScilabLexerConstants.COMMENT; + } + + [^ \t\n]+ { + return ScilabLexerConstants.COMMENT; + } + + {eol} { + yybegin(YYINITIAL); + return ScilabLexerConstants.DEFAULT; + } +} + +<BREAKSTRING> { + {break} { + breakstring = true; + return ScilabLexerConstants.SPECIAL; + } + + " " { + return ScilabLexerConstants.WHITE; + } + + "\t" { + return ScilabLexerConstants.TAB; + } + + {comment} { + transposable = false; + yypushback(2); + yybegin(COMMENT); + } + + . | + {eol} { + return ScilabLexerConstants.DEFAULT; + } +} + +<<EOF>> { + return ScilabLexerConstants.EOF; + } diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/CommentManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/CommentManager.java new file mode 100755 index 000000000..71b2bfa97 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/CommentManager.java @@ -0,0 +1,160 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +/** + * Class Comment Manager + * @author Calixte DENIZET + */ +public class CommentManager { + + private static final String COM = "//"; + private static final char DEMICOM = '/'; + private static final String EOL = "\n"; + + private ScilabDocument doc; + private Element elem; + + /** + * Constructor + * @param doc the document to comment + */ + public CommentManager(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + } + + + /** + * Comment a line + * @param line the line number + */ + public void commentLine(int line) { + Element startL = elem.getElement(line); + int sstart = startL.getStartOffset(); + + try { + doc.insertString(sstart, COM, null); + } catch (BadLocationException e) { + e.printStackTrace(); + return; + } + } + + /** + * Uncomment a line + * @param line the line number + * @return true if the line has been uncommented + */ + public boolean uncommentLine(int line) { + Element startL = elem.getElement(line); + int sstart = startL.getStartOffset(); + int send = startL.getEndOffset() - 1; + + try { + String str = doc.getText(sstart, send - sstart); + Pattern pat = Pattern.compile("([ \t]*)//"); + Matcher matcher = pat.matcher(str); + if (matcher.find()) { + str = matcher.replaceFirst("$1"); + doc.replace(sstart, send - sstart, str, null); + return true; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + return false; + } + + /** + * Comment several lines + * @param start the beginning position in the doc + * @param end the ending position in the doc + * @return an array of length 2 containing the new positions + */ + public int[] commentLines(int start, int end) { + int first = elem.getElementIndex(start); + int last = elem.getElementIndex(end); + int[] ret = new int[] {start, end}; + + for (int i = first; i <= last; i++) { + commentLine(i); + ret[1] += 2; + } + + ret[0] += 2; + + return ret; + } + + /** + * Comment a part of a line + * @param position in the doc + */ + public void commentText(int position) { + try { + doc.insertString(position, COM, null); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Un-Comment several lines + * @param start the beginning position in the doc + * @param end the ending position in the doc + * @return an array of length 2 containing the new positions + */ + public int[] uncommentLines(int start, int end) { + int first = elem.getElementIndex(start); + int last = elem.getElementIndex(end); + int[] ret = new int[] {start, end}; + + boolean unc = uncommentLine(first); + if (unc) { + ret[0] -= 2; + ret[1] -= 2; + } + + for (int i = first + 1; i <= last; i++) { + unc = uncommentLine(i); + if (unc) { + ret[1] -= 2; + } + } + + return ret; + } + + /** + * UnComment a part of a line + * @param start position start + */ + public void uncommentText(int start) { + try { + int end = elem.getElement(elem.getElementIndex(start)).getEndOffset(); + if (end - start >= 2 && COM.equals(doc.getText(start, 2))) { + doc.remove(start, 2); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/CompoundUndoManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/CompoundUndoManager.java new file mode 100755 index 000000000..6d17f9d4a --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/CompoundUndoManager.java @@ -0,0 +1,238 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bernard HUGUENEY + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.UndoableEditEvent; +import javax.swing.text.AbstractDocument; +import javax.swing.text.Segment; +import javax.swing.text.BadLocationException; +import javax.swing.undo.CompoundEdit; +import javax.swing.undo.UndoManager; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.CannotRedoException; + +/** + * Class CompoundUndoManager + * @author Bernard Hugueney + * @author Calixte DENIZET + * + */ +public class CompoundUndoManager extends UndoManager { + + private static final long serialVersionUID = 2400488911410627080L; + + private CompoundEdit compoundEdit; + private ScilabDocument sdoc; + private Segment seg = new Segment(); + private boolean remove; + private int nbEdits; + private char[] breaks; + private int prevLine; + private boolean oneShot; + + /** + * Constructor + * @param sdoc the ScilabDocument where we want to make undo/redo + */ + public CompoundUndoManager(ScilabDocument sdoc) { + super(); + this.sdoc = sdoc; + setLimit(-1); + setBreakingChars(" \n"); + } + + /** + * setBreakingChars defines the breaking chars which break a compound when they are encountered. + * @param breaks the breaking chars + */ + public void setBreakingChars(String breaks) { + this.breaks = breaks.toCharArray(); + } + + /** + * getBreakingChars returns the breaking chars + * @return the breaking chars + */ + public String getBreakingChars() { + return new String(breaks); + } + + /** + * startCompoundEdit + */ + public void startCompoundEdit() { + if (compoundEdit == null && sdoc.getEditorPane() != null) { + compoundEdit = new CompoundEdit(); + addEdit(compoundEdit); + ++nbEdits; + if (sdoc.getEditorPane().getEditor() != null) { + sdoc.getEditorPane().getEditor().enableUndoButton(true); + } + } + } + + /** + * endCompoundEdit + */ + public void endCompoundEdit() { + if (compoundEdit != null && sdoc.getEditorPane() != null) { + compoundEdit.end(); + compoundEdit = null; + } + } + + /** + * Enable one shot, i.e. if several modifs on one char occurred then they + * can be added in the same CompoundEdit. + * @param b true if one shot must be enabled + */ + public void enableOneShot(boolean b) { + this.oneShot = b; + } + + /** + * undo + */ + public void undo() { + endCompoundEdit(); + try { + super.undo(); + if (sdoc.getEditorPane().getEditor() != null) { + sdoc.getEditorPane().getEditor().enableRedoButton(true); + } + --nbEdits; + if (nbEdits == 0) { + sdoc.setContentModified(false); + } + if (!canUndo() && sdoc.getEditorPane().getEditor() != null) { + sdoc.getEditorPane().getEditor().enableUndoButton(false); + } + } catch (CannotUndoException e) { + return; + } + } + + /** + * redo + */ + public void redo() { + endCompoundEdit(); + try { + super.redo(); + if (sdoc.getEditorPane().getEditor() != null) { + sdoc.getEditorPane().getEditor().enableUndoButton(true); + } + ++nbEdits; + if (nbEdits == 0) { + sdoc.setContentModified(false); + } + if (!canRedo() && sdoc.getEditorPane().getEditor() != null) { + sdoc.getEditorPane().getEditor().enableRedoButton(false); + } + } catch (CannotRedoException e) { + return; + } + } + + /** + * Enable or not the Undo and Redo buttons + */ + public void enableUndoRedoButtons() { + endCompoundEdit(); + if (sdoc.getEditorPane().getEditor() != null) { + sdoc.getEditorPane().getEditor().enableRedoButton(canRedo()); + sdoc.getEditorPane().getEditor().enableUndoButton(canUndo()); + } + } + + /** + * isAtReference + * @return boolean + */ + public boolean isAtReference() { + return nbEdits == 0; + } + + /** + * setReference + */ + public void setReference() { + nbEdits = 0; + } + + /** + * discardAllEdits + */ + public void discardAllEdits() { + endCompoundEdit(); + super.discardAllEdits(); + } + + /** + * undoableEditHappened handles an undo-strategy : + * - single chars are grouped in a same Edit but if this char is in breaks (e.g. ' ' or '\n') + * - removed chars are grouped too + * - if several modifs are made in different lines, then these are considered like several groups + * - if a modif contains more than one char, then it is considered like one group. + * @param e UndoableEditEvent + */ + public void undoableEditHappened(UndoableEditEvent e) { + DocumentEvent event = (AbstractDocument.DefaultDocumentEvent) e.getEdit(); + if (sdoc.getEditorPane() != null) { + if (!oneShot && event.getLength() == 1) { + if (!remove && event.getType() == DocumentEvent.EventType.REMOVE) { + endCompoundEdit(); + remove = true; + } + + if (remove && event.getType() == DocumentEvent.EventType.INSERT) { + endCompoundEdit(); + remove = false; + } + + try { + sdoc.getText(event.getOffset(), 1, seg); + boolean br = false; + for (int i = 0; i < breaks.length && !br; i++) { + br = seg.array[seg.offset] == breaks[i]; + } + if (!remove && br) { + // there is a problem when the window is splitted + // two compoundEdits are created ! + endCompoundEdit(); + startCompoundEdit(); + compoundEdit.addEdit(e.getEdit()); + endCompoundEdit(); + return; + } else { + if (sdoc.getDefaultRootElement().getElementIndex(event.getOffset()) != prevLine) { + prevLine = sdoc.getDefaultRootElement().getElementIndex(event.getOffset()); + endCompoundEdit(); + } + startCompoundEdit(); + compoundEdit.addEdit(e.getEdit()); + return; + } + } catch (BadLocationException ex) { + ex.printStackTrace(); + } + } else { + startCompoundEdit(); + compoundEdit.addEdit(e.getEdit()); + } + } + } +} + diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/EditorComponent.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/EditorComponent.java new file mode 100755 index 000000000..c2c3e20dc --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/EditorComponent.java @@ -0,0 +1,108 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.BorderLayout; +import java.awt.Component; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; + +import org.scilab.modules.scinotes.utils.ScilabScrollPane; + +/** + * @author Calixte DENIZET + */ +public class EditorComponent extends JPanel { + + private static final long serialVersionUID = -1466505151043279504L; + + private ScilabEditorPane editor; + private JScrollPane scroll; + private JSplitPane split; + private Component bottom; + + /** + * Default constructor + * @param the EditorPane to display + */ + public EditorComponent(ScilabEditorPane editor) { + super(new BorderLayout()); + this.editor = editor; + scroll = new ScilabScrollPane(editor); + add(scroll); + } + + /** + * @return the scrollpane + */ + public JScrollPane getScrollPane() { + return scroll; + } + + /** + * @return the editorpane + */ + public ScilabEditorPane getEditorPane() { + return editor; + } + + /** + * @param split the split to use + */ + public void setSplitPane(JSplitPane split) { + this.split = split; + remove(scroll); + add(split, BorderLayout.CENTER); + split.setVisible(true); + setVisible(true); + revalidate(); + } + + /** + * @return the splitpane + */ + public JSplitPane getSplitPane() { + return split; + } + + /** + * @return true if the view is splited + */ + public boolean isSplited() { + return split != null; + } + + /** + * @param comp the component to insert at the bottom of this panel + */ + public void insertBottomComponent(Component comp) { + if (comp == null) { + if (bottom != null) { + remove(bottom); + } + } else { + bottom = comp; + add(comp, BorderLayout.PAGE_END); + } + revalidate(); + } + + /** + * @return the component at the bottom + */ + public Component getBottom() { + return bottom; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/FunctionScanner.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/FunctionScanner.java new file mode 100755 index 000000000..473eedff7 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/FunctionScanner.java @@ -0,0 +1,1524 @@ +/* The following code was generated by JFlex 1.4.3 on 05/04/13 17:28 */ + +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.io.IOException; +import java.util.List; +import java.util.ArrayList; +import javax.swing.text.Element; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") + +/** + * This class is a scanner generated by + * <a href="http://www.jflex.de/">JFlex</a> 1.4.3 + * on 05/04/13 17:28 from the specification file + * <tt>function.jflex</tt> + */ +public final class FunctionScanner { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int RETS = 8; + public static final int TYPEID = 4; + public static final int BROKEN = 12; + public static final int YYINITIAL = 0; + public static final int ARGS = 10; + public static final int FUNNAME = 6; + public static final int FUNCTION = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\1\1\2\25\0\1\1\1\7\1\0\2\7\1\5\2\0" + + "\1\25\1\11\2\0\1\26\1\0\1\4\1\3\12\6\1\0\1\12" + + "\1\0\1\10\1\0\1\7\1\0\32\7\1\22\1\0\1\27\1\0" + + "\1\7\1\0\2\7\1\16\1\24\1\23\1\13\2\7\1\20\4\7" + + "\1\15\1\21\4\7\1\17\1\14\5\7\uff85\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\7\0\4\1\1\2\1\3\1\4\1\5\1\1\1\6" + + "\1\7\1\1\1\10\1\1\1\11\1\12\1\4\1\1" + + "\1\13\1\4\2\1\1\14\1\1\2\15\12\0\1\16" + + "\10\0\1\17\2\0\1\20\15\0\1\21\3\0\1\22"; + + private static int [] zzUnpackAction() { + int [] result = new int[74]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do { + result[j++] = value; + } while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + List<String> returnValues; + List<String> argsValues; + String functionName; + int end; + + private ScilabDocument doc; + private String id; + private boolean inRETS; + + public FunctionScanner(ScilabDocument doc) { + this.doc = doc; + returnValues = new ArrayList(); + argsValues = new ArrayList(); + } + + public String getFunctionName() { + return functionName; + } + + public List<String> getReturnValues() { + return returnValues; + } + + public List<String> getArgsValues() { + return argsValues; + } + + public int getLineType(int p0, int p1) { + try { + returnValues = new ArrayList(); + argsValues = new ArrayList(); + end = p1; + yyreset(new ScilabDocumentReader(doc, p0, p1)); + yybegin(BROKEN); + int broken = yylex(); + + yyreset(new ScilabDocumentReader(doc, p0, p1)); + while (true) { + int ret = yylex(); + if (ret != ScilabDocument.ScilabLeafElement.BROKEN) { + return ret | broken; + } + Element elem = doc.getDefaultRootElement(); + int start = end + 1; + elem = elem.getElement(elem.getElementIndex(end + 1)); + end = elem.getEndOffset(); + yyreset(new ScilabDocumentReader(doc, elem.getStartOffset(), end)); + if (inRETS) { + inRETS = false; + yybegin(RETS); + } else { + yybegin(ARGS); + } + } + } catch (IOException e) { + return ScilabDocument.ScilabLeafElement.NOTHING; + } + } + + public FunctionInfo getFunctionInfo() { + return new FunctionInfo(functionName, returnValues, argsValues); + } + + public class FunctionInfo { + public String functionName; + public List<String> returnValues; + public List<String> argsValues; + + public FunctionInfo(String name, List ret, List args) { + this.functionName = name; + this.returnValues = ret; + this.argsValues = args; + } + } + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + public FunctionScanner(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public FunctionScanner(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 94) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do { + map[j++] = value; + } while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return <code>false</code>, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead - zzStartRead); + + /* translate stored positions */ + zzEndRead -= zzStartRead; + zzCurrentPos -= zzStartRead; + zzMarkedPos -= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos * 2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length - zzEndRead); + + if (numRead > 0) { + zzEndRead += numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) { + zzReader.close(); + } + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * <b>cannot</b> be reused (internal buffer is discarded and lost). + * Lexical state is set to <tt>ZZ_INITIAL</tt>. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos - zzStartRead ); + } + + + /** + * Returns the character at position <tt>pos</tt> from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead + pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos - zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) { + zzScanError(ZZ_PUSHBACK_2BIG); + } + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public int yylex() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar += zzMarkedPosL - zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = zzBufferL[zzCurrentPosL++]; + } else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + zzInput = zzCMapL[zzInput]; + + boolean zzIsFinal = false; + boolean zzNoLookAhead = false; + + zzForNext: { + switch (zzState) { + case 0: + switch (zzInput) { + case 1: + zzIsFinal = true; + zzState = 8; + break zzForNext; + case 11: + zzIsFinal = true; + zzState = 9; + break zzForNext; + case 19: + zzIsFinal = true; + zzState = 10; + break zzForNext; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + } + + case 1: + switch (zzInput) { + case 5: + case 7: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 19: + case 20: + zzIsFinal = true; + zzState = 11; + break zzForNext; + case 18: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 12; + break zzForNext; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + } + + case 2: + switch (zzInput) { + case 1: + zzIsFinal = true; + zzState = 13; + break zzForNext; + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 14; + break zzForNext; + case 3: + zzIsFinal = true; + zzState = 15; + break zzForNext; + case 8: + zzIsFinal = true; + zzState = 16; + break zzForNext; + case 21: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 17; + break zzForNext; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + } + + case 3: + switch (zzInput) { + case 0: + case 4: + case 6: + case 8: + case 9: + case 10: + case 18: + case 22: + case 23: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + case 1: + zzIsFinal = true; + zzState = 18; + break zzForNext; + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 19; + break zzForNext; + case 3: + zzIsFinal = true; + zzState = 20; + break zzForNext; + case 21: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 22; + break zzForNext; + default: + zzIsFinal = true; + zzState = 21; + break zzForNext; + } + + case 4: + switch (zzInput) { + case 0: + case 2: + case 3: + case 6: + case 8: + case 9: + case 10: + case 18: + case 21: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + case 1: + zzIsFinal = true; + zzState = 23; + break zzForNext; + case 4: + zzIsFinal = true; + zzState = 24; + break zzForNext; + case 22: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 26; + break zzForNext; + case 23: + zzIsFinal = true; + zzState = 27; + break zzForNext; + default: + zzIsFinal = true; + zzState = 25; + break zzForNext; + } + + case 5: + switch (zzInput) { + case 0: + case 2: + case 3: + case 6: + case 8: + case 10: + case 18: + case 21: + case 23: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + case 1: + zzIsFinal = true; + zzState = 23; + break zzForNext; + case 22: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 26; + break zzForNext; + case 4: + zzIsFinal = true; + zzState = 28; + break zzForNext; + case 9: + zzIsFinal = true; + zzState = 30; + break zzForNext; + default: + zzIsFinal = true; + zzState = 29; + break zzForNext; + } + + case 6: + switch (zzInput) { + case 4: + zzIsFinal = true; + zzState = 32; + break zzForNext; + default: + zzIsFinal = true; + zzState = 31; + break zzForNext; + } + + case 8: + switch (zzInput) { + case 1: + zzState = 33; + break zzForNext; + case 11: + zzState = 34; + break zzForNext; + case 19: + zzState = 35; + break zzForNext; + default: + break zzForAction; + } + + case 9: + switch (zzInput) { + case 12: + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 10: + switch (zzInput) { + case 13: + zzState = 37; + break zzForNext; + default: + break zzForAction; + } + + case 11: + switch (zzInput) { + case 6: + case 7: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 19: + case 20: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 13: + switch (zzInput) { + case 1: + zzIsFinal = true; + break zzForNext; + case 8: + zzIsFinal = true; + zzState = 16; + break zzForNext; + default: + break zzForAction; + } + + case 15: + switch (zzInput) { + case 3: + zzState = 38; + break zzForNext; + default: + break zzForAction; + } + + case 16: + switch (zzInput) { + case 1: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 18: + switch (zzInput) { + case 21: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 22; + break zzForNext; + case 1: + zzState = 39; + break zzForNext; + default: + break zzForAction; + } + + case 20: + switch (zzInput) { + case 3: + zzState = 40; + break zzForNext; + default: + break zzForAction; + } + + case 21: + switch (zzInput) { + case 6: + case 7: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 19: + case 20: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 23: + switch (zzInput) { + case 1: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 24: + switch (zzInput) { + case 4: + zzState = 41; + break zzForNext; + default: + break zzForAction; + } + + case 25: + switch (zzInput) { + case 6: + case 7: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 19: + case 20: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 27: + switch (zzInput) { + case 1: + zzState = 42; + break zzForNext; + case 8: + zzIsFinal = true; + zzState = 43; + break zzForNext; + default: + break zzForAction; + } + + case 28: + switch (zzInput) { + case 4: + zzState = 44; + break zzForNext; + default: + break zzForAction; + } + + case 29: + switch (zzInput) { + case 6: + case 7: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 19: + case 20: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 30: + switch (zzInput) { + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 19; + break zzForNext; + case 1: + case 10: + case 22: + zzState = 45; + break zzForNext; + case 3: + zzState = 46; + break zzForNext; + default: + break zzForAction; + } + + case 31: + switch (zzInput) { + case 4: + zzState = 48; + break zzForNext; + default: + zzState = 47; + break zzForNext; + } + + case 32: + switch (zzInput) { + case 4: + zzState = 44; + break zzForNext; + default: + zzState = 47; + break zzForNext; + } + + case 33: + switch (zzInput) { + case 1: + break zzForNext; + case 11: + zzState = 34; + break zzForNext; + case 19: + zzState = 35; + break zzForNext; + default: + break zzForAction; + } + + case 34: + switch (zzInput) { + case 12: + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 35: + switch (zzInput) { + case 13: + zzState = 37; + break zzForNext; + default: + break zzForAction; + } + + case 36: + switch (zzInput) { + case 13: + zzState = 49; + break zzForNext; + default: + break zzForAction; + } + + case 37: + switch (zzInput) { + case 20: + zzState = 50; + break zzForNext; + default: + break zzForAction; + } + + case 38: + switch (zzInput) { + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 14; + break zzForNext; + default: + break zzForNext; + } + + case 39: + switch (zzInput) { + case 21: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 22; + break zzForNext; + case 1: + break zzForNext; + default: + break zzForAction; + } + + case 40: + switch (zzInput) { + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 19; + break zzForNext; + default: + break zzForNext; + } + + case 41: + switch (zzInput) { + case 4: + break zzForNext; + case 1: + zzState = 51; + break zzForNext; + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 52; + break zzForNext; + case 3: + zzState = 53; + break zzForNext; + default: + break zzForAction; + } + + case 42: + switch (zzInput) { + case 1: + break zzForNext; + case 8: + zzIsFinal = true; + zzState = 43; + break zzForNext; + default: + break zzForAction; + } + + case 43: + switch (zzInput) { + case 1: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 44: + switch (zzInput) { + case 4: + break zzForNext; + case 1: + zzState = 54; + break zzForNext; + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 55; + break zzForNext; + case 3: + zzState = 56; + break zzForNext; + default: + break zzForAction; + } + + case 45: + switch (zzInput) { + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 19; + break zzForNext; + case 1: + case 10: + case 22: + break zzForNext; + case 3: + zzState = 46; + break zzForNext; + default: + break zzForAction; + } + + case 46: + switch (zzInput) { + case 3: + zzState = 40; + break zzForNext; + default: + break zzForAction; + } + + case 47: + switch (zzInput) { + case 4: + zzState = 48; + break zzForNext; + default: + break zzForNext; + } + + case 48: + switch (zzInput) { + case 4: + zzState = 44; + break zzForNext; + default: + zzState = 47; + break zzForNext; + } + + case 49: + switch (zzInput) { + case 14: + zzState = 57; + break zzForNext; + default: + break zzForAction; + } + + case 50: + switch (zzInput) { + case 11: + zzState = 58; + break zzForNext; + default: + break zzForAction; + } + + case 51: + switch (zzInput) { + case 1: + break zzForNext; + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 52; + break zzForNext; + case 3: + zzState = 53; + break zzForNext; + default: + break zzForAction; + } + + case 53: + switch (zzInput) { + case 3: + zzState = 59; + break zzForNext; + default: + break zzForAction; + } + + case 54: + switch (zzInput) { + case 1: + break zzForNext; + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 55; + break zzForNext; + case 3: + zzState = 56; + break zzForNext; + default: + break zzForAction; + } + + case 56: + switch (zzInput) { + case 3: + zzState = 60; + break zzForNext; + default: + break zzForAction; + } + + case 57: + switch (zzInput) { + case 15: + zzState = 61; + break zzForNext; + default: + break zzForAction; + } + + case 58: + switch (zzInput) { + case 12: + zzState = 62; + break zzForNext; + default: + break zzForAction; + } + + case 59: + switch (zzInput) { + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 52; + break zzForNext; + default: + break zzForNext; + } + + case 60: + switch (zzInput) { + case 2: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 55; + break zzForNext; + default: + break zzForNext; + } + + case 61: + switch (zzInput) { + case 16: + zzState = 63; + break zzForNext; + default: + break zzForAction; + } + + case 62: + switch (zzInput) { + case 13: + zzState = 64; + break zzForNext; + default: + break zzForAction; + } + + case 63: + switch (zzInput) { + case 17: + zzState = 65; + break zzForNext; + default: + break zzForAction; + } + + case 64: + switch (zzInput) { + case 14: + zzState = 66; + break zzForNext; + default: + break zzForAction; + } + + case 65: + switch (zzInput) { + case 13: + zzState = 67; + break zzForNext; + default: + break zzForAction; + } + + case 66: + switch (zzInput) { + case 15: + zzState = 68; + break zzForNext; + default: + break zzForAction; + } + + case 67: + switch (zzInput) { + case 18: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 12; + break zzForNext; + case 1: + zzIsFinal = true; + zzState = 69; + break zzForNext; + default: + break zzForAction; + } + + case 68: + switch (zzInput) { + case 16: + zzState = 70; + break zzForNext; + default: + break zzForAction; + } + + case 69: + switch (zzInput) { + case 1: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 70: + switch (zzInput) { + case 17: + zzState = 71; + break zzForNext; + default: + break zzForAction; + } + + case 71: + switch (zzInput) { + case 13: + zzState = 72; + break zzForNext; + default: + break zzForAction; + } + + case 72: + switch (zzInput) { + case 6: + case 7: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 19: + case 20: + break zzForAction; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 73; + break zzForNext; + } + + default: + // if this is ever reached, there is a serious bug in JFlex + zzScanError(ZZ_UNKNOWN_ERROR); + break; + } + } + + if ( zzIsFinal ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( zzNoLookAhead ) { + break zzForAction; + } + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 5 : + { + functionName = id; + return ScilabDocument.ScilabLeafElement.FUN; + } + case 19: + break; + case 15: { + inRETS = true; + return ScilabDocument.ScilabLeafElement.BROKEN; + } + case 20: + break; + case 9: { + functionName = yytext(); + } + case 21: + break; + case 13: { + return 0; + } + case 22: + break; + case 6: { + returnValues.add(id); + yybegin(FUNNAME); + } + case 23: + break; + case 1: { + return ScilabDocument.ScilabLeafElement.NOTHING; + } + case 24: + break; + case 16: { + return ScilabDocument.ScilabLeafElement.BROKEN; + } + case 25: + break; + case 12: { + argsValues.add(yytext()); + } + case 26: + break; + case 2: { + id = yytext(); + yybegin(TYPEID); + } + case 27: + break; + case 10: { + yybegin(ARGS); + } + case 28: + break; + case 18: { + return ScilabDocument.ScilabLeafElement.ENDFUN; + } + case 29: + break; + case 3: { + yybegin(RETS); + } + case 30: + break; + case 8: { + return ScilabDocument.ScilabLeafElement.FUN; + } + case 31: + break; + case 7: { + functionName = id; + yybegin(ARGS); + } + case 32: + break; + case 17: { + yybegin(FUNCTION); + } + case 33: + break; + case 11: { + returnValues.add(yytext()); + } + case 34: + break; + case 14: { + yybegin(FUNNAME); + } + case 35: + break; + case 4: { + } + case 36: + break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return ScilabDocument.ScilabLeafElement.NOTHING; + } + } else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/HelpOnTypingManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/HelpOnTypingManager.java new file mode 100755 index 000000000..c9b610cde --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/HelpOnTypingManager.java @@ -0,0 +1,249 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.event.KeyListener; +import java.awt.event.KeyEvent; + +import javax.swing.text.BadLocationException; + +import org.scilab.modules.commons.xml.XConfiguration; + +/** + * This class handles the help on typing + * @author Calixte DENIZET + */ +public final class HelpOnTypingManager implements KeyListener { + + private static HelpOnTypingManager instance; + private boolean openers; + private boolean keywords; + + /** + * Constructor + */ + private HelpOnTypingManager() { + super(); + instance = this; + openers = SciNotesOptions.getSciNotesDisplay().autoCompleteOpeners; + keywords = SciNotesOptions.getSciNotesDisplay().autoCompleteKeywords; + } + + /** + * Clean + */ + public static void close() { + instance = null; + } + + /** + * @return the singleton instance of HelpOnTypingManager + */ + public static HelpOnTypingManager getInstance() { + if (instance == null) { + instance = new HelpOnTypingManager(); + } + + return instance; + } + + /** + * @param b true if autocompletion on '(', '{', ... + */ + public void enableOpeners(boolean b) { + openers = b; + SciNotesOptions.getSciNotesDisplay().autoCompleteOpeners = b; + XConfiguration.set(XConfiguration.getXConfigurationDocument(), SciNotesOptions.DISPLAYPATH + "/@auto-complete-openers", Boolean.toString(b)); + } + + /** + * @param b true if autocompletion on 'if', 'function', ... + */ + public void enableKeywords(boolean b) { + keywords = b; + SciNotesOptions.getSciNotesDisplay().autoCompleteKeywords = b; + XConfiguration.set(XConfiguration.getXConfigurationDocument(), SciNotesOptions.DISPLAYPATH + "/@auto-complete-keywords", Boolean.toString(b)); + } + + /** + * @return true if help on typing is active + */ + public boolean isActive() { + return openers || keywords; + } + + /** + * @return true if help on typing for the openers is active + */ + public boolean isOpenersActive() { + return openers; + } + + /** + * @return true if help on typing for the openers is active + */ + public boolean isKeywordsActive() { + return keywords; + } + + /** + * Nothing ! + * @param e the event + */ + public void keyPressed(KeyEvent e) { } + + /** + * Nothing ! + * @param e the event + */ + public void keyReleased(KeyEvent e) { } + + /** + * Called when a key is typed + * @param e the event + */ + public void keyTyped(KeyEvent e) { + char c = e.getKeyChar(); + ScilabEditorPane textPane = ScilabEditorPane.getFocusedPane(); + ScilabDocument doc = (ScilabDocument) textPane.getDocument(); + if (isActive() && c != KeyEvent.CHAR_UNDEFINED && textPane.getSelectionStart() == textPane.getSelectionEnd()) { + int pos = textPane.getCaretPosition(); + if (c == ' ' && e.getModifiers() == 0) { + int end = doc.getDefaultRootElement().getElement(doc.getDefaultRootElement().getElementIndex(pos)).getEndOffset() - 1; + /* the following test is used to know if an insertion in the line is done */ + if (pos == end) { + try { + doc.insertString(pos, " ", null); + e.consume(); + KeywordEvent kwe = textPane.getKeywordEvent(pos); + int[] ret; + String kw; + switch (kwe.getType()) { + case ScilabLexerConstants.OSKEYWORD : + kw = doc.getText(kwe.getStart(), kwe.getLength()); + if ("if".equals(kw)) { + if (complete("end", textPane, doc, pos)) { + doc.insertString(pos + 1, " then\nend", null); + ret = textPane.getIndentManager().indentDoc(pos + 1, pos + 9); + textPane.setCaretPosition(ret[0]); + } + } else if (!"end".equals(kw)) { + if (complete("end", textPane, doc, pos)) { + doc.insertString(pos + 1, "\nend", null); + ret = textPane.getIndentManager().indentDoc(pos + 1, pos + 4); + textPane.setCaretPosition(ret[0]); + } + } + break; + case ScilabLexerConstants.SKEYWORD : + kw = doc.getText(kwe.getStart(), kwe.getLength()); + if ("elseif".equals(kw)) { + doc.insertString(pos + 1, " then", null); + textPane.setCaretPosition(pos + 1); + } + break; + case ScilabLexerConstants.FKEYWORD : + /* We have 'function' or 'endfunction' */ + if ("f".equals(doc.getText(kwe.getStart(), 1)) && complete("endfunction", textPane, doc, pos)) { + doc.insertString(pos + 1, "()\nendfunction", null); + textPane.getIndentManager().indentDoc(pos + 3, pos + 14); + textPane.setCaretPosition(pos + 1); + } + break; + default : + } + } catch (BadLocationException exc) { + System.err.println(exc); + } + } + } else if (openers) { + if (SciNotesOptions.getSciNotesPreferences().completeAtEOL) { + int end = doc.getDefaultRootElement().getElement(doc.getDefaultRootElement().getElementIndex(pos)).getEndOffset() - 1; + if (pos != end) { + return; + } + } + + try { + String str; + switch (c) { + case '(' : + if (complete(')', textPane, doc, pos)) { + str = "()"; + } else { + return; + } + break; + case '[' : + if (complete(']', textPane, doc, pos)) { + str = "[]"; + } else { + return; + } + break; + case '{' : + if (complete('}', textPane, doc, pos)) { + str = "{}"; + } else { + return; + } + break; + case '\"' : + str = "\"\""; + break; + default : + return; + } + + doc.insertString(pos, str, null); + e.consume(); + textPane.setCaretPosition(pos + 1); + } catch (BadLocationException exc) { + System.err.println(exc); + } + } + } + } + + private static boolean complete(char next, ScilabEditorPane pane, ScilabDocument doc, int pos) throws BadLocationException { + MatchingBlockManager matchLR = pane.getMatchingBlockManager(true); + MatchingBlockScanner scanner = matchLR.getScanner(); + MatchingBlockScanner.MatchingPositions mpos = scanner.getNextBlock(pos, true); + if (mpos != null) { + char mc = doc.getText(mpos.secondB, 1).charAt(0); + if (mc != next) { + return true; + } + + return false; + } + + return true; + } + + private static boolean complete(String next, ScilabEditorPane pane, ScilabDocument doc, int pos) throws BadLocationException { + MatchingBlockManager matchLR = pane.getMatchingBlockManager(true); + MatchingBlockScanner scanner = matchLR.getScanner(); + MatchingBlockScanner.MatchingPositions mpos = scanner.getNextBlock(pos, true); + if (mpos != null) { + String ms = doc.getText(mpos.secondB, mpos.secondE - mpos.secondB); + if (!next.equals(ms)) { + return true; + } + + return false; + } + + return true; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/IndentManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/IndentManager.java new file mode 100755 index 000000000..7c4948a6a --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/IndentManager.java @@ -0,0 +1,246 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import javax.swing.text.Element; +import javax.swing.text.Segment; +import javax.swing.text.BadLocationException; + +/** + * This class handle the indentation level + * @author Calixte DENIZET + */ +public class IndentManager { + + private ScilabDocument doc; + private Element elem; + private IndentScanner scanner; + private char indentChar = ' '; + private int num = 4; + private boolean isPsychoRigid = true; + + /** + * Constructor. + * @param doc the doc to indent + */ + public IndentManager(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + scanner = new IndentScanner(doc); + } + + /** + * Set the character to use to indent and if the indentChar is not '\t', then + * num represents the number of whites to indent. If the variable isPsychoRigid + * is true, then the indent level is strict and the indentation of a line doesn't + * depend of the difference the two previous. For example (with isPsychoRigid false): + * if a == 1 then + * -----if b == 1 then + * -----c = 1 ... + * + * If isPsychoRigid is true and num equals to 3 : + * if a == 1 then + * -------if b == 1 then + * ---c = 1 ... + * + * The user decided to increase the indent but the PsychoRigid mode says that the + * indent level is 3. + * + * @param indentChar the char use to indent + * @param num the number of chars use to indent + * @param isPsychoRigid for the psycho-rigid mode + */ + public void setProperties(char indentChar, int num, boolean isPsychoRigid) { + this.indentChar = indentChar; + if (indentChar != '\t') { + this.num = num; + } else { + this.num = 1; + } + this.isPsychoRigid = isPsychoRigid; + } + + /** + * The same as setProperties in keeping the same psycho-rigid mode + * @param indentChar the char use to indent + * @param num the number of chars use to indent + */ + public void setProperties(char indentChar, int num) { + setProperties(indentChar, num, isPsychoRigid); + } + + /** + * Set the psycho-rigid mode or not + * @param b the mode + */ + public void setPsychoRigidMode(boolean b) { + this.isPsychoRigid = b; + } + + /** + * Indent the lines of this doc containing start and end. + * @param start the start + * @param end the end + * @return an array of length 2 containing the new start and the new end of the indented text + */ + public int[] indentDoc(int start, int end) { + try { + if (start > end ) { + end = start; + } + int[] level = new int[2]; + int lineStart = elem.getElementIndex(start); + int lineEnd = elem.getElementIndex(end); + int[] tabs = new int[lineEnd - lineStart + 1]; + int[] ret = new int[2]; + + int[] ind = new int[2]; + + getNums(lineStart - 1, ind); + if (lineStart > 0) { + scanner.getIndentLevel(elem.getElement(lineStart - 1).getStartOffset(), level); + tabs[0] = ind[1] + level[1] * num; + } + + for (int lineNumber = 0; lineNumber <= lineEnd - lineStart; lineNumber++) { + int pos = elem.getElement(lineNumber + lineStart).getEndOffset() - 1; + scanner.getIndentLevel(pos, level); + tabs[lineNumber] = Math.max(tabs[lineNumber] - level[0] * num, 0); + if (lineNumber != lineEnd - lineStart) { + tabs[lineNumber + 1] = tabs[lineNumber] + level[1] * num; + } + } + + Segment seg = new Segment(); + StringBuffer buffer = new StringBuffer(); + int e = start; + + for (int lineNumber = lineStart; lineNumber <= lineEnd; lineNumber++) { + if (lineNumber < lineEnd) { + e = elem.getElement(lineNumber).getEndOffset(); + } else { + e = elem.getElement(lineNumber).getEndOffset() - 1; + } + int t = elem.getElement(lineNumber).getStartOffset() + scanner.getTabsAtBeginning(lineNumber); + if (e - t + 1 == 0) { + e = t; + } + doc.getText(t, e - t, seg); + ret[0] = start; + if (e > t + 1) { + char[] str = new char[tabs[lineNumber - lineStart]]; + for (int i = 0; i < str.length; i++) { + str[i] = indentChar; + } + buffer.append(str); + if (lineNumber == lineStart) { + ret[0] = start + str.length - scanner.getTabsAtBeginning(lineNumber); + } + } + buffer.append(seg.array, seg.offset, seg.count); + } + + int sstart = elem.getElement(lineStart).getStartOffset(); + doc.replace(sstart, e - sstart, buffer.toString(), null); + ret[1] = sstart + buffer.length() - (e - end - 1); + return ret; + } catch (BadLocationException e) { + System.err.println(e); + return null; + } + } + + /** + * Indent the line of this doc containing position. + * @param position the position in the doc + */ + public void indentDoc(int position) { + if (doc.getAutoIndent()) { + int[] level = new int[2]; + int[] ind = new int[2]; + + try { + int lineNumber = elem.getElementIndex(position); + int pos = elem.getElement(lineNumber).getEndOffset() - 1; + + /* - level[0] is the left shift (else, elseif, ...) for the current line + - level[1] is the right shift for the next line */ + scanner.getIndentLevel(pos, level); + + int remove = 0; + if (lineNumber >= 0) { + /* - ind[0] is equal to the number of "\t" or " " of the previous line + - ind[1] for the current line */ + getNums(lineNumber, ind); + if (level[0] > 0 && ind[0] <= ind[1]) { + remove = level[0] * num; + + if (lineNumber > 0 && ind[0] == ind[1]) { + /* Bug 7550 : + prev and cur line are at the same level + if cur should be indented, then we don't remove tabs */ + int posp = elem.getElement(lineNumber - 1).getEndOffset() - 1; + int[] levelp = new int[2]; + scanner.getIndentLevel(posp, levelp); + if (levelp[1] != 0) { + remove = 0; + } + } + + if (ind[1] < remove) { + remove = ind[1]; + } + if (remove != 0) { + int startL = elem.getElement(lineNumber).getStartOffset(); + doc.remove(startL, remove); + } + } + } + + int len = ind[1] + level[1] * num - remove; + char[] str = new char[len]; + for (int i = 0; i < len; i++) { + str[i] = indentChar; + } + + doc.insertString(pos + 1 - remove, new String(str), null); + } catch (BadLocationException e) { + System.err.println(e); + } + } + } + + /** + * @return the scanner used by this IndentManager + */ + public IndentScanner getIndentScanner() { + return scanner; + } + + /** + * Calculate the indentation of the two previous lines and the number of chars + * used to indent is modified if we are not in psycho-rigid mode + * @param lineNumber the number of the line + * @param ind an array of length 2 which will contain the indent level of the line and the previous + */ + private void getNums(int lineNumber, int[] ind) { + ind[1] = scanner.getIndentNumber(lineNumber, indentChar); + ind[0] = scanner.getIndentNumber(lineNumber - 1, indentChar); + if (!isPsychoRigid) { + int m = ind[1] - ind[0]; + if (m > 0) { + num = m; + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/IndentScanner.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/IndentScanner.java new file mode 100755 index 000000000..c5d09edee --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/IndentScanner.java @@ -0,0 +1,1925 @@ +/* The following code was generated by JFlex 1.4.3 on 23/05/12 15:23 */ + +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.io.IOException; +import javax.swing.text.Element; +import javax.swing.text.BadLocationException; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") + +/** + * This class is a scanner generated by + * <a href="http://www.jflex.de/">JFlex</a> 1.4.3 + * on 23/05/12 15:23 from the specification file + * <tt>./jflex/indentation.jflex</tt> + */ +public final class IndentScanner { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int BEG = 8; + public static final int TAB = 6; + public static final int WHITE = 4; + public static final int YYINITIAL = 0; + public static final int INDENT = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 5 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\31\1\1\2\0\1\4\22\0\1\30\1\3\1\6\3\3" + + "\1\0\1\5\1\0\1\7\5\0\1\2\12\3\5\0\1\3\1\0" + + "\32\3\2\0\1\7\1\0\1\3\1\0\1\27\1\3\1\13\1\26" + + "\1\23\1\10\1\3\1\21\1\15\2\3\1\22\1\3\1\12\1\16" + + "\2\3\1\17\1\25\1\14\1\11\1\3\1\20\1\3\1\24\1\3" + + "\2\0\1\7\uff82\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\2\1\2\0\1\2\1\3\13\2\2\1\1\4" + + "\11\0\1\2\4\0\1\4\17\0\1\2\1\0\1\5" + + "\6\0\1\2\4\0\1\6\1\0\1\2\1\6\4\0" + + "\1\2\2\0\2\2\4\0\1\2\2\0\1\2\1\0" + + "\3\2\1\5"; + + private static int [] zzUnpackAction() { + int [] result = new int[92]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do { + result[j++] = value; + } while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + private ScilabDocument doc; + private Element elem; + + public IndentScanner(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + } + + public int getIndentNumber(int lineNumber, char type) { + if (lineNumber < 0) { + return 0; + } + try { + Element line = elem.getElement(lineNumber); + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + yyreset(new ScilabDocumentReader(doc, startL, endL)); + switch (type) { + case ' ': + yybegin(WHITE); + break; + case '\t': + yybegin(TAB); + break; + default: + yybegin(WHITE); + } + return yylex(); + } catch (IOException e) { + return 0; + } + } + + public int getTabsAtBeginning(int pos) { + Element line = elem.getElement(pos); + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + try { + yyreset(new ScilabDocumentReader(doc, startL, endL)); + yybegin(BEG); + if (yylex() == 1) { + return yylength(); + } + } catch (IOException e) { + return 0; + } + return 0; + } + + public void getIndentLevel(int pos, int[] level) { + Element line = elem.getElement(elem.getElementIndex(pos)); + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + level[0] = 0; + level[1] = 0; + try { + yyreset(new ScilabDocumentReader(doc, startL, endL)); + yybegin(INDENT); + do { + switch (yylex()) { + case 0: + break; + case 1: + level[1]++; + break; + case 2: + if (level[1] > 0) { + level[1]--; + } else { + level[0]++; + } + break; + case 3: + if (level[1] == 0) { + level[0]++; + level[1]++; + } + } + } while (zzMarkedPos != 0); + } catch (IOException e) { } + } + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + public IndentScanner(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public IndentScanner(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 106) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do { + map[j++] = value; + } while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return <code>false</code>, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead - zzStartRead); + + /* translate stored positions */ + zzEndRead -= zzStartRead; + zzCurrentPos -= zzStartRead; + zzMarkedPos -= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos * 2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length - zzEndRead); + + if (numRead > 0) { + zzEndRead += numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) { + zzReader.close(); + } + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * <b>cannot</b> be reused (internal buffer is discarded and lost). + * Lexical state is set to <tt>ZZ_INITIAL</tt>. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos - zzStartRead ); + } + + + /** + * Returns the character at position <tt>pos</tt> from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead + pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos - zzStartRead; + } + + + /** + * Reports an error that occurred while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) { + zzScanError(ZZ_PUSHBACK_2BIG); + } + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public int yylex() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar += zzMarkedPosL - zzStartRead; + + if (zzMarkedPosL > zzStartRead) { + switch (zzBufferL[zzMarkedPosL - 1]) { + case '\n': + case '\u000B': + case '\u000C': + case '\u0085': + case '\u2028': + case '\u2029': + zzAtBOL = true; + break; + case '\r': + if (zzMarkedPosL < zzEndReadL) { + zzAtBOL = zzBufferL[zzMarkedPosL] != '\n'; + } else if (zzAtEOF) { + zzAtBOL = false; + } else { + boolean eof = zzRefill(); + zzMarkedPosL = zzMarkedPos; + zzEndReadL = zzEndRead; + zzBufferL = zzBuffer; + if (eof) { + zzAtBOL = false; + } else { + zzAtBOL = zzBufferL[zzMarkedPosL] != '\n'; + } + } + break; + default: + zzAtBOL = false; + } + } + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + if (zzAtBOL) { + zzState = ZZ_LEXSTATE[zzLexicalState + 1]; + } else { + zzState = ZZ_LEXSTATE[zzLexicalState]; + } + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = zzBufferL[zzCurrentPosL++]; + } else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + zzInput = zzCMapL[zzInput]; + + boolean zzIsFinal = false; + boolean zzNoLookAhead = false; + + zzForNext: { + switch (zzState) { + case 1: + switch (zzInput) { + case 0: + case 4: + case 24: + case 25: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 1: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + case 2: + zzIsFinal = true; + zzState = 8; + break zzForNext; + case 5: + case 6: + zzIsFinal = true; + zzState = 10; + break zzForNext; + case 7: + zzIsFinal = true; + zzState = 11; + break zzForNext; + case 8: + zzIsFinal = true; + zzState = 12; + break zzForNext; + case 11: + zzIsFinal = true; + zzState = 13; + break zzForNext; + case 12: + zzIsFinal = true; + zzState = 14; + break zzForNext; + case 13: + zzIsFinal = true; + zzState = 15; + break zzForNext; + case 16: + zzIsFinal = true; + zzState = 16; + break zzForNext; + case 19: + zzIsFinal = true; + zzState = 17; + break zzForNext; + case 21: + zzIsFinal = true; + zzState = 18; + break zzForNext; + default: + zzIsFinal = true; + zzState = 9; + break zzForNext; + } + + case 2: + switch (zzInput) { + case 24: + zzIsFinal = true; + zzState = 19; + break zzForNext; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + } + + case 3: + switch (zzInput) { + case 25: + zzIsFinal = true; + zzState = 20; + break zzForNext; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 7; + break zzForNext; + } + + case 4: + switch (zzInput) { + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + } + + case 5: + switch (zzInput) { + case 24: + case 25: + zzIsFinal = true; + zzState = 21; + break zzForNext; + default: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + } + + case 8: + switch (zzInput) { + case 2: + zzState = 22; + break zzForNext; + default: + break zzForAction; + } + + case 9: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + default: + break zzForAction; + } + + case 10: + switch (zzInput) { + case 5: + case 6: + zzIsFinal = true; + zzState = 31; + break zzForNext; + case 1: + case 4: + break zzForAction; + default: + zzState = 30; + break zzForNext; + } + + case 11: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 12: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 9: + zzState = 32; + break zzForNext; + case 14: + zzState = 33; + break zzForNext; + default: + break zzForAction; + } + + case 13: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 23: + zzState = 34; + break zzForNext; + default: + break zzForAction; + } + + case 14: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 15: + zzState = 35; + break zzForNext; + default: + break zzForAction; + } + + case 15: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 8: + zzIsFinal = true; + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 16: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 17: + zzState = 37; + break zzForNext; + default: + break zzForAction; + } + + case 17: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 19: + zzState = 28; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 10: + zzState = 38; + break zzForNext; + case 18: + zzState = 39; + break zzForNext; + default: + break zzForAction; + } + + case 18: + switch (zzInput) { + case 5: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + case 8: + zzState = 23; + break zzForNext; + case 11: + zzState = 24; + break zzForNext; + case 12: + zzState = 25; + break zzForNext; + case 13: + zzState = 26; + break zzForNext; + case 16: + zzState = 27; + break zzForNext; + case 21: + zzState = 29; + break zzForNext; + case 19: + zzState = 40; + break zzForNext; + default: + break zzForAction; + } + + case 19: + switch (zzInput) { + case 24: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 20: + switch (zzInput) { + case 25: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 21: + switch (zzInput) { + case 24: + case 25: + zzIsFinal = true; + break zzForNext; + default: + break zzForAction; + } + + case 22: + switch (zzInput) { + case 1: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForNext; + } + + case 23: + switch (zzInput) { + case 9: + zzState = 41; + break zzForNext; + case 14: + zzState = 42; + break zzForNext; + default: + break zzForAction; + } + + case 24: + switch (zzInput) { + case 23: + zzState = 43; + break zzForNext; + default: + break zzForAction; + } + + case 25: + switch (zzInput) { + case 15: + zzState = 44; + break zzForNext; + default: + break zzForAction; + } + + case 26: + switch (zzInput) { + case 8: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 27: + switch (zzInput) { + case 17: + zzState = 45; + break zzForNext; + default: + break zzForAction; + } + + case 28: + switch (zzInput) { + case 10: + zzState = 46; + break zzForNext; + case 18: + zzState = 47; + break zzForNext; + default: + break zzForAction; + } + + case 29: + switch (zzInput) { + case 19: + zzState = 48; + break zzForNext; + default: + break zzForAction; + } + + case 30: + switch (zzInput) { + case 5: + case 6: + zzIsFinal = true; + zzState = 31; + break zzForNext; + case 1: + case 4: + break zzForAction; + default: + break zzForNext; + } + + case 31: + switch (zzInput) { + case 5: + case 6: + zzState = 30; + break zzForNext; + default: + break zzForAction; + } + + case 32: + switch (zzInput) { + case 10: + zzState = 49; + break zzForNext; + default: + break zzForAction; + } + + case 33: + switch (zzInput) { + case 15: + zzIsFinal = true; + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 34: + switch (zzInput) { + case 12: + zzState = 50; + break zzForNext; + case 21: + zzState = 51; + break zzForNext; + default: + break zzForAction; + } + + case 35: + switch (zzInput) { + case 20: + zzIsFinal = true; + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 36: + switch (zzInput) { + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 37: + switch (zzInput) { + case 13: + zzState = 53; + break zzForNext; + default: + break zzForAction; + } + + case 38: + switch (zzInput) { + case 22: + zzIsFinal = true; + zzState = 54; + break zzForNext; + default: + break zzForAction; + } + + case 39: + switch (zzInput) { + case 21: + zzState = 55; + break zzForNext; + default: + break zzForAction; + } + + case 40: + switch (zzInput) { + case 10: + zzState = 46; + break zzForNext; + case 18: + zzState = 56; + break zzForNext; + default: + break zzForAction; + } + + case 41: + switch (zzInput) { + case 10: + zzState = 57; + break zzForNext; + default: + break zzForAction; + } + + case 42: + switch (zzInput) { + case 15: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 43: + switch (zzInput) { + case 12: + zzState = 58; + break zzForNext; + case 21: + zzState = 59; + break zzForNext; + default: + break zzForAction; + } + + case 44: + switch (zzInput) { + case 20: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 45: + switch (zzInput) { + case 13: + zzState = 60; + break zzForNext; + default: + break zzForAction; + } + + case 46: + switch (zzInput) { + case 22: + zzIsFinal = true; + zzState = 61; + break zzForNext; + default: + break zzForAction; + } + + case 47: + switch (zzInput) { + case 21: + zzState = 62; + break zzForNext; + default: + break zzForAction; + } + + case 48: + switch (zzInput) { + case 18: + zzState = 63; + break zzForNext; + default: + break zzForAction; + } + + case 49: + switch (zzInput) { + case 11: + zzState = 64; + break zzForNext; + default: + break zzForAction; + } + + case 50: + switch (zzInput) { + case 11: + zzState = 65; + break zzForNext; + default: + break zzForAction; + } + + case 51: + switch (zzInput) { + case 19: + zzIsFinal = true; + zzState = 66; + break zzForNext; + default: + break zzForAction; + } + + case 52: + switch (zzInput) { + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + break zzForNext; + } + + case 53: + switch (zzInput) { + case 18: + zzState = 67; + break zzForNext; + default: + break zzForAction; + } + + case 54: + switch (zzInput) { + case 8: + zzIsFinal = true; + zzState = 68; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 55: + switch (zzInput) { + case 19: + zzIsFinal = true; + zzState = 69; + break zzForNext; + default: + break zzForAction; + } + + case 56: + switch (zzInput) { + case 21: + zzState = 62; + break zzForNext; + case 19: + zzState = 70; + break zzForNext; + default: + break zzForAction; + } + + case 57: + switch (zzInput) { + case 11: + zzState = 71; + break zzForNext; + default: + break zzForAction; + } + + case 58: + switch (zzInput) { + case 11: + zzState = 72; + break zzForNext; + default: + break zzForAction; + } + + case 59: + switch (zzInput) { + case 19: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 60: + switch (zzInput) { + case 18: + zzState = 59; + break zzForNext; + default: + break zzForAction; + } + + case 61: + switch (zzInput) { + case 8: + zzState = 73; + break zzForNext; + default: + break zzForAction; + } + + case 62: + switch (zzInput) { + case 19: + zzIsFinal = true; + zzState = 74; + break zzForNext; + default: + break zzForAction; + } + + case 63: + switch (zzInput) { + case 19: + zzState = 75; + break zzForNext; + default: + break zzForAction; + } + + case 64: + switch (zzInput) { + case 12: + zzState = 76; + break zzForNext; + default: + break zzForAction; + } + + case 65: + switch (zzInput) { + case 17: + zzIsFinal = true; + zzState = 66; + break zzForNext; + default: + break zzForAction; + } + + case 66: + switch (zzInput) { + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 67: + switch (zzInput) { + case 19: + zzIsFinal = true; + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 68: + switch (zzInput) { + case 9: + zzIsFinal = true; + zzState = 77; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 69: + switch (zzInput) { + case 13: + zzIsFinal = true; + zzState = 78; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 70: + switch (zzInput) { + case 11: + zzState = 79; + break zzForNext; + default: + break zzForAction; + } + + case 71: + switch (zzInput) { + case 12: + zzState = 80; + break zzForNext; + default: + break zzForAction; + } + + case 72: + switch (zzInput) { + case 17: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 73: + switch (zzInput) { + case 9: + zzState = 41; + break zzForNext; + default: + break zzForAction; + } + + case 74: + switch (zzInput) { + case 13: + zzState = 26; + break zzForNext; + default: + break zzForAction; + } + + case 75: + switch (zzInput) { + case 11: + zzState = 81; + break zzForNext; + default: + break zzForAction; + } + + case 76: + switch (zzInput) { + case 13: + zzState = 82; + break zzForNext; + default: + break zzForAction; + } + + case 77: + switch (zzInput) { + case 10: + zzIsFinal = true; + zzState = 83; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 78: + switch (zzInput) { + case 8: + zzIsFinal = true; + zzState = 66; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 79: + switch (zzInput) { + case 12: + zzIsFinal = true; + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 80: + switch (zzInput) { + case 13: + zzState = 84; + break zzForNext; + default: + break zzForAction; + } + + case 81: + switch (zzInput) { + case 12: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 82: + switch (zzInput) { + case 14: + zzState = 85; + break zzForNext; + default: + break zzForAction; + } + + case 83: + switch (zzInput) { + case 11: + zzIsFinal = true; + zzState = 86; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 84: + switch (zzInput) { + case 14: + zzState = 87; + break zzForNext; + default: + break zzForAction; + } + + case 85: + switch (zzInput) { + case 10: + zzIsFinal = true; + zzState = 36; + break zzForNext; + default: + break zzForAction; + } + + case 86: + switch (zzInput) { + case 12: + zzIsFinal = true; + zzState = 88; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 87: + switch (zzInput) { + case 10: + zzIsFinal = true; + zzNoLookAhead = true; + zzState = 6; + break zzForNext; + default: + break zzForAction; + } + + case 88: + switch (zzInput) { + case 13: + zzIsFinal = true; + zzState = 89; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 89: + switch (zzInput) { + case 14: + zzIsFinal = true; + zzState = 90; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 90: + switch (zzInput) { + case 10: + zzIsFinal = true; + zzState = 91; + break zzForNext; + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + case 91: + switch (zzInput) { + case 0: + case 1: + case 2: + case 4: + case 5: + case 6: + case 7: + case 24: + case 25: + break zzForAction; + default: + zzIsFinal = true; + zzState = 52; + break zzForNext; + } + + default: + // if this is ever reached, there is a serious bug in JFlex + zzScanError(ZZ_UNKNOWN_ERROR); + break; + } + } + + if ( zzIsFinal ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( zzNoLookAhead ) { + break zzForAction; + } + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 5 : + { + return 2; + } + case 7: + break; + case 6: { + return 3; + } + case 8: + break; + case 1: { + return yylength(); + } + case 9: + break; + case 3: { + return 0; + } + case 10: + break; + case 4: { + return 1; + } + case 11: + break; + case 2: { + } + case 12: + break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return 0; + } + } else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordAdapter.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordAdapter.java new file mode 100755 index 000000000..a4636d5a3 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordAdapter.java @@ -0,0 +1,69 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +/** + * An adaptater for the interface KeywordListener + * @author Calixte DENIZET + */ +public abstract class KeywordAdapter implements KeywordListener { + + private int type; + + /** + * Constructor + * @param type the type of listener (ONMOUSECLICKED or ONMOUSEOVER) + */ + protected KeywordAdapter(int type) { + this.type = type; + } + + /** + * @return the type of this listener + */ + public int getType() { + return type; + } + + /** + * Called when a keyword is caught + * @param e a KeywordEvent + */ + public abstract void caughtKeyword(KeywordEvent e); + + /** + * Class to have a KeywordListener attached to a MouseClicked event + */ + public abstract static class MouseClickedAdapter extends KeywordAdapter { + + /** + * Constructor + */ + public MouseClickedAdapter() { + super(ONMOUSECLICKED); + } + } + + /** + * Class to have a KeywordListener attached to a MouseOver event + */ + public abstract static class MouseOverAdapter extends KeywordAdapter { + + /** + * Constructor + */ + public MouseOverAdapter() { + super(ONMOUSEOVER); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordEvent.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordEvent.java new file mode 100755 index 000000000..eacd5f87f --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordEvent.java @@ -0,0 +1,90 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.util.EventObject; + +import javax.swing.text.Document; +import javax.swing.text.BadLocationException; + +/** + * Used to handle an event generated on a keyword + * @author Calixte DENIZET + */ +public class KeywordEvent extends EventObject { + + private static final long serialVersionUID = 4505744754595572108L; + + private int start; + private int length; + private int type; + private EventObject event; + + /** + * Constructor + * @param source the Object where the event occurred + * @param event the MouseEvent which generated this event + * @param type the type of the keyword + * @param start the position of the keyword in the doc + * @param length the length of the keyword + */ + public KeywordEvent(Object source, EventObject event, int type, int start, int length) { + super(source); + this.start = start; + this.length = length; + this.type = type; + this.event = event; + } + + /** + * @return the position of the keyword in the doc + */ + public int getStart() { + return start; + } + + /** + * @return the length of the keyword + */ + public int getLength() { + return length; + } + + /** + * @return the type of the keyword + */ + public int getType() { + return type; + } + + /** + * @return the event which generated this event + */ + public EventObject getEvent() { + return event; + } + + /** + * {@inheritDoc} + */ + public String toString() { + ScilabEditorPane sep = (ScilabEditorPane) getSource(); + Document doc = sep.getDocument(); + try { + return doc.getText(start, length) + " at position " + start + " with type " + type; + } catch (BadLocationException e) { + System.err.println(e); + } + return ""; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordListener.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordListener.java new file mode 100755 index 000000000..62ef32386 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/KeywordListener.java @@ -0,0 +1,43 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.util.EventListener; + +/** + * The interface KeywordListener is useful to listen to a keyword event. + * @author Calixte DENIZET + */ +public interface KeywordListener extends EventListener { + + /** + * ONMOUSECLICKED + */ + int ONMOUSECLICKED = 1; + + /** + * ONMOUSEOVER + */ + int ONMOUSEOVER = 2; + + /** + * Called when a keyword is caught + * @param e a KeywordEvent + */ + void caughtKeyword(KeywordEvent e); + + /** + * @return the type of the listener + */ + int getType(); +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/MatchingBlockManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/MatchingBlockManager.java new file mode 100755 index 000000000..d1bfaeace --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/MatchingBlockManager.java @@ -0,0 +1,522 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import java.util.Set; + +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Element; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import javax.swing.text.View; + +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * Useful to match opening and closing keywords from left to right or from right to left + * @author Calixte DENIZET + */ +public class MatchingBlockManager { + + private ScilabDocument doc; + private ScilabEditorPane pane; + private MatchingBlockScanner scanner; + private Highlighter highlighter; + private MatchingBlockScanner.MatchingPositions smpos; + private Highlighter.HighlightPainter kwPainter; + private Highlighter.HighlightPainter ocPainter; + private Object first; + private Object second; + private boolean insideOc; + private boolean insideKw; + private boolean ocIncluded; + private boolean kwIncluded; + private boolean lr; + private boolean isOCMouseover; + private boolean isKWMouseover; + private MouseOverMatcher mouseover; + + /** + * Constructor + * @param doc the doc to highlight + * @param pane the ScilabEditorPane associated with this Manager + * @param lr if true the matching is from left to right + * @param highlighter the highlighter to use + */ + public MatchingBlockManager(ScilabDocument doc, ScilabEditorPane pane, boolean lr, Highlighter highlighter) { + this.doc = doc; + this.pane = pane; + this.scanner = new MatchingBlockScanner(doc); + this.highlighter = highlighter; + this.lr = lr; + } + + /** + * @return the scanner used by thhis manager + */ + public MatchingBlockScanner getScanner() { + return scanner; + } + + /** + * Set the painter for the matching open/close keywords (such as '('/')' or '['/']'). + * The contents between the matchings is highlighted. + * @param filled true if a filled rectangle must be used to highlight + * @param color the color of the painter + **/ + public void setPainterForOpenClose(boolean filled, boolean included, Color color) { + this.insideOc = true; + this.ocIncluded = included; + update(); + ocPainter = new InsideLinePainter(filled, false, color); + } + + /** + * Set the painter for the matching open/close keywords (such as '('/')' or '['/']'). + * The matchings are highlighted. + * @param type one of the three values : ScilabKeywordsPainter.FILLED + * ScilabKeywordsPainter.UNDERLINED + * ScilabKeywordsPainter.FRAMED + * @param color the color of the painter + **/ + public void setPainterForOpenClose(int type, Color color) { + this.insideOc = false; + update(); + ocPainter = new ScilabKeywordsPainter(color, type); + } + + /** + * Set the painter for the matching open/close keywords (such as '('/')' or '['/']'). + * Properties are found in the file scinotesConfiguration.xml + * The contents between the matchings is highlighted. + **/ + public void setPainterForOpenClose() { + setPainterForOpenClose(SciNotesOptions.getSciNotesDisplay().bracketsHighlightment, SciNotesOptions.getSciNotesDisplay().bracketsColor); + if (SciNotesOptions.getSciNotesDisplay().bracketsOnmouseover) { + isOCMouseover = true; + activateMouseOver(); + } else { + isOCMouseover = false; + disableMouseOver(); + } + } + + /** + * Set the painter for the matching keywords (such as 'function' and 'endfunction'). + * The contents between the matchings is highlighted. + * @param filled true if a filled rectangle must be used to highlight + * @param color the color of the painter + **/ + public void setPainterForKeywords(boolean filled, boolean strict, boolean included, Color color) { + this.insideKw = true; + this.kwIncluded = included; + update(); + kwPainter = new InsideLinePainter(filled, strict, color); + } + + /** + * Set the painter for the matching keywords (such as 'function' and 'endfunction'). + * The matchings are highlighted. + * @param type one of the three values : ScilabKeywordsPainter.FILLED + * ScilabKeywordsPainter.UNDERLINED + * ScilabKeywordsPainter.FRAMED + * @param color the color of the painter + **/ + public void setPainterForKeywords(int type, Color color) { + this.insideKw = false; + update(); + kwPainter = new ScilabKeywordsPainter(color, type); + } + + /** + * Set the painter for the matching keywords. + * Properties are found in the file scinotesConfiguration.xml + * The contents between the matchings is highlighted. + **/ + public void setPainterForKeywords() { + setPainterForKeywords(SciNotesOptions.getSciNotesDisplay().keywordsHighlightment == ScilabKeywordsPainter.FILLED, true, false, SciNotesOptions.getSciNotesDisplay().keywordsColor); + if (SciNotesOptions.getSciNotesDisplay().keywordsOnmouseover) { + isKWMouseover = true; + activateMouseOver(); + } else { + isKWMouseover = false; + disableMouseOver(); + } + } + + /** + * Set the defaults from scinotesConfiguration.xml + */ + public void setDefaults() { + if (SciNotesOptions.getSciNotesDisplay().highlightKeywords) { + setPainterForKeywords(); + } + if (SciNotesOptions.getSciNotesDisplay().highlightBrackets) { + setPainterForOpenClose(); + } + } + + public void configurationChanged(SciNotesConfiguration.Conf conf) { + if (conf.display) { + setDefaults(); + } + } + + /** + * Activate this MatchingBlockManager to listen to the KeywordEvent generate by a MouseOver. + */ + public void activateMouseOver() { + if (mouseover == null) { + mouseover = new MouseOverMatcher(); + } + pane.addKeywordListener(mouseover); + } + + /** + * Activate this MatchingBlockManager to listen to the KeywordEvent generate by a MouseOver. + */ + public void disableMouseOver() { + if (mouseover != null && !isOCMouseover && !isKWMouseover) { + pane.removeKeywordListener(mouseover); + mouseover = null; + } + } + + /** + * Desactivate this MatchingBlockManager to listen to the KeywordEvent generate by a MouseOver. + */ + public void desactivateMouseOver() { + if (mouseover != null) { + pane.removeKeywordListener(mouseover); + mouseover = null; + } + } + + /** + * Remove the highlights if they exist. + */ + public synchronized void update() { + if (first != null) { + highlighter.removeHighlight(first); + first = null; + } + if (second != null) { + highlighter.removeHighlight(second); + second = null; + } + } + + /** + * Search the matching keywords + * @param tok the type of the token at the position pos in the document + * @param pos the positon in the doc + */ + public synchronized void searchMatchingBlock(boolean isMouse, int tok, int pos) { + MatchingBlockScanner.MatchingPositions mpos = null; + if (ScilabLexerConstants.isMatchable(tok)) { + mpos = scanner.getMatchingBlock(pos, lr); + } + if (mpos != this.smpos) { + this.smpos = mpos; + try { + if (first != null) { + highlighter.removeHighlight(first); + if (second != null) { + highlighter.removeHighlight(second); + } + } + if (mpos != null) { + if (ScilabLexerConstants.isOpenClose(tok) && ocPainter != null && (!isMouse || isOCMouseover)) { + createHighlights(mpos, insideOc, ocIncluded, ocPainter); + } else if (kwPainter != null && (!isMouse || isKWMouseover)) { + createHighlights(mpos, insideKw, kwIncluded, kwPainter); + } + } + } catch (NullPointerException e) { } + } + } + + /** + * Create the highlights + * @param mpos the position of the matching keywords + * @param inside true if we look at the contents between the keywords + * @param hp the painter to use + */ + private void createHighlights(MatchingBlockScanner.MatchingPositions mpos, + boolean inside, boolean included, Highlighter.HighlightPainter hp) { + try { + if (!inside) { + first = highlighter.addHighlight(mpos.firstB, mpos.firstE, hp); + second = highlighter.addHighlight(mpos.secondB, mpos.secondE, hp); + } else { + if (lr) { + if (included) { + first = highlighter.addHighlight(mpos.firstB, mpos.secondE, hp); + } else { + first = highlighter.addHighlight(mpos.firstE, mpos.secondB, hp); + } + } else { + if (included) { + first = highlighter.addHighlight(mpos.secondB, mpos.firstE, hp); + } else { + first = highlighter.addHighlight(mpos.secondE, mpos.firstB, hp); + } + } + } + } catch (BadLocationException e) { + System.err.println(e); + } + } + + /** + * Inner class used to retriev infos from scinotesConfiguration.xml + */ + public static class Parameters { + + /** + * The color + */ + public Color color; + + /** + * Inside or not + */ + public boolean inside; + + /** + * Strict or not + */ + public boolean strict; + + /** + * Included or not + */ + public boolean included; + + /** + * The type + */ + public int type; + + /** + * The onmouseover + */ + public boolean onmouseover; + + /** + * Constructor + * @param color the color + * @param inside inside or not + * @param type the type + * @param onmouseover a boolean + */ + public Parameters(Color color, boolean inside, boolean strict, boolean included, int type, boolean onmouseover) { + this.color = color; + this.inside = inside; + this.type = type; + this.strict = strict; + this.included = included; + this.onmouseover = onmouseover; + } + } + + /** + * Inner class to highlight matching keywords + */ + public class ScilabKeywordsPainter extends DefaultHighlighter.DefaultHighlightPainter { + + /** + * FILLED + */ + public static final int FILLED = 0; + + /** + * UNDERLINED + */ + public static final int UNDERLINED = 1; + + /** + * FRAMED + */ + public static final int FRAMED = 2; + + private Color color; + private int type; + + /** + * Constructor + * @param color the color to paint + * @param type must be FILLED, UNDERLINED or FRAMED + */ + public ScilabKeywordsPainter(Color color, int type) { + super(color); + this.color = color; + this.type = type; + } + + /** + * paintLayer + * @param g Graphics + * @param offs0 the beginning + * @param offs1 the end + * @param bounds the bounds + * @param c the text component where to paint + * @param view the view to use + * @return the shape containg the highlighted text + */ + public Shape paintLayer(Graphics g, int offs0, int offs1, + Shape bounds, JTextComponent c, View view) { + try { + Rectangle r = (Rectangle) view.modelToView(offs0, Position.Bias.Forward, + offs1, Position.Bias.Backward, bounds); + g.setColor(color); + + switch (type) { + case UNDERLINED : + g.drawLine(r.x, r.y + r.height - 1, r.x + r.width - 1, r.y + r.height - 1); + return r; + case FRAMED : + g.drawRect(r.x, r.y, r.width - 1, r.height - 1); + return r; + case FILLED : + default : + g.fillRect(r.x, r.y, r.width, r.height); + return r; + } + } catch (BadLocationException e) { + return null; + } + } + } + + /** + * Inner class to highlight the content inside two keywords. + * The highlight depends on the position of the content. + */ + class InsideLinePainter implements Highlighter.HighlightPainter { + + private boolean filled; + private boolean strict; + private Color color; + + /** + * Constructor + * @param filled if the highlighted rectangle must be filled + * @param color the color to paint + */ + protected InsideLinePainter(boolean filled, boolean strict, Color color) { + this.filled = filled; + this.strict = strict; + this.color = color; + } + + /** + * Implements a strategy to render contents depending on the position of these + * @param g Graphics + * @param pos0 the beginning + * @param pos1 the end + * @param bounds the bounds + * @param c the text component where to paint + */ + public void paint(Graphics g, int pos0, int pos1, Shape bounds, JTextComponent c) { + try { + Rectangle alloc = bounds.getBounds(); + Rectangle p0 = c.modelToView(pos0); + Rectangle p1 = c.modelToView(pos1); + g.setColor(color); + + if (p0.y == p1.y) { + Rectangle r = p0.union(p1); + if (filled) { + g.fillRect(r.x, r.y, r.width, r.height); + } else { + g.drawRect(r.x, r.y, r.width - 1, r.height - 1); + } + } else { + Element root = doc.getDefaultRootElement(); + int line0 = root.getElementIndex(pos0); + int line1 = root.getElementIndex(pos1); + Rectangle r0 = c.modelToView(root.getElement(line0).getEndOffset()); + Rectangle r1 = c.modelToView(root.getElement(line1).getStartOffset()); + if (line0 != line1) { + if (!strict) { + if (filled) { + g.fillRect(p0.x, p0.y, alloc.width, p0.height); + g.fillRect(alloc.x, p0.y + p0.height, alloc.width, r0.y - p0.y - p0.height); + + if (r1.y != p1.y) { + g.fillRect(r1.x, r1.y, alloc.width, r1.height); + } + g.fillRect(r1.x, p1.y, p1.x, r1.height); + } else { + g.drawRect(p0.x, p0.y, alloc.width - 1, p0.height - 1); + g.drawRect(alloc.x, p0.y + p0.height, alloc.width - 1, r0.y - p0.y - p0.height - 1); + + if (r1.y != p1.y) { + g.drawRect(r1.x, r1.y, alloc.width, r1.height - 1); + } + g.drawRect(r1.x, p1.y, p1.x, r1.height - 1); + } + } + + if (filled) { + g.fillRect(alloc.x, r0.y, alloc.width, r1.y - r0.y); + } else { + g.drawRect(alloc.x, r0.y, alloc.width - 1, r1.y - r0.y - 1); + } + } else { + /* This part of the code has been copied (for the filling) from DefaultHighlighter.java */ + int w = alloc.x + alloc.width - p0.x; + if (filled) { + g.fillRect(p0.x, p0.y, w, p0.height); + if ((p0.y + p0.height) != p1.y) { + g.fillRect(alloc.x, p0.y + p0.height, alloc.width, p1.y - (p0.y + p0.height)); + } + g.fillRect(alloc.x, p1.y, (p1.x - alloc.x), p1.height); + } else { + g.drawRect(p0.x, p0.y, w - 1, p0.height - 1); + if ((p0.y + p0.height) != p1.y) { + g.drawRect(alloc.x, p0.y + p0.height, alloc.width - 1, p1.y - (p0.y + p0.height) - 1); + } + g.drawRect(alloc.x, p1.y, (p1.x - alloc.x) - 1, p1.height - 1); + } + } + } + } catch (BadLocationException e) { } + } + } + + /** + * Inner class to highlight on a KeywordEvent generated by a ONMOUSEOVER + */ + class MouseOverMatcher extends KeywordAdapter.MouseOverAdapter { + + /** + * What to do when the event occurred + * @param e the event + */ + public void caughtKeyword(KeywordEvent e) { + if (lr) { + searchMatchingBlock(true, e.getType(), e.getStart()); + } else { + searchMatchingBlock(true, e.getType(), e.getStart() + e.getLength()); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/MatchingBlockScanner.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/MatchingBlockScanner.java new file mode 100755 index 000000000..b709f8c12 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/MatchingBlockScanner.java @@ -0,0 +1,2085 @@ +/* The following code was generated by JFlex 1.4.3 on 28/04/14 15:53 */ + +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.io.IOException; +import javax.swing.text.Element; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") + +/** + * This class is a scanner generated by + * <a href="http://www.jflex.de/">JFlex</a> 1.4.3 + * on 28/04/14 15:53 from the specification file + * <tt>matchingblock.jflex</tt> + */ +public final class MatchingBlockScanner { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 256; + + /** lexical states */ + public static final int OPENCLOSE = 6; + public static final int LR = 2; + public static final int YYINITIAL = 0; + public static final int PSNART = 10; + public static final int CLOSEOPEN = 8; + public static final int SPEC = 12; + public static final int RL = 4; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\12\0\1\1\2\0\1\3\23\0\1\6\1\10\1\6\1\4\1\5"+ + "\1\0\1\7\1\30\1\11\5\0\1\2\12\4\5\0\1\6\1\0"+ + "\32\6\1\30\1\0\1\11\1\0\1\6\1\0\2\6\1\23\1\31"+ + "\1\21\1\13\1\6\1\17\1\12\2\6\1\20\1\6\1\27\1\14"+ + "\2\6\1\15\1\22\1\24\1\26\1\6\1\16\1\6\1\25\1\6"+ + "\1\30\1\0\1\11\uff82\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\7\0\6\1\1\2\6\1\1\3\2\1\1\4\6\1"+ + "\1\2\1\1\11\2\1\5\1\6\1\0\1\7\2\0"+ + "\1\1\1\3\6\1\11\0\1\2\6\0\1\3\13\0"+ + "\2\1\1\2\2\1\6\0\1\1\1\2\3\0\1\2"+ + "\7\0\5\1\11\0\1\3\4\0\3\1\13\0\2\1"+ + "\7\0\2\1\6\0\1\1\1\0\1\2\3\0\3\1"+ + "\3\0\1\1\2\0\1\2"; + + private static int [] zzUnpackAction() { + int [] result = new int[173]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + private ScilabDocument doc; + private Element elem; + private boolean transp = false; + private ScilabLexer scilabLexer; + private int start; + private int end; + private int savePos; + + public MatchingBlockScanner(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + this.scilabLexer = doc.createLexer(); + } + + public MatchingPositions getNextBlock(int pos, boolean lr) { + int s = 1; + transp = false; + try { + if (lr) { + start = pos; + end = doc.getEndPosition().getOffset(); + yyreset(new ScilabDocumentReader(doc, start, end)); + yybegin(LR); + } else { + start = pos - 1; + end = 0; + yyreset(new ScilabDocumentReader(doc, true, start, end)); + yybegin(RL); + } + do { + if (yylex() == 0) { + s--; + } else { + s++; + } + } while (zzMarkedPos != 0 && s != 0); + } catch (IOException e) { + return null; + } + if (s == 0) { + if (lr) { + return new MatchingPositions(pos, pos, pos + yychar, pos + yychar + (transp?(yylength()-1):yylength())); + } else { + return new MatchingPositions(pos, pos, pos - yychar - yylength(), pos - yychar); + } + } + + return null; + } + + public MatchingPositions getMatchingBlock(int pos, boolean lr) { + int p1, s = 1; + transp = false; + try { + if (lr) { + start = pos; + end = doc.getEndPosition().getOffset(); + yyreset(new ScilabDocumentReader(doc, start, end)); + yybegin(OPENCLOSE); + if (yylex() != 1) { + return null; + } + + p1 = pos + yylength(); + yybegin(LR); + } else { + start = pos - 1; + end = 0; + yyreset(new ScilabDocumentReader(doc, true, start, end)); + yybegin(CLOSEOPEN); + if (yylex() != 1) { + return null; + } + p1 = pos - yylength(); + yybegin(RL); + } + + do { + if (yylex() == 0) { + s--; + } else { + s++; + } + } while (zzMarkedPos != 0 && s != 0); + } catch (IOException e) { + return null; + } + if (s == 0) { + if (lr) { + return new MatchingPositions(pos, p1, pos + yychar, pos + yychar + (transp?(yylength()-1):yylength())); + } else { + return new MatchingPositions(p1, pos, pos - yychar - yylength(), pos - yychar); + } + } + + return null; + } + + public final class MatchingPositions { + public int firstB; + public int firstE; + public int secondB; + public int secondE; + + private MatchingPositions(int x1, int x2, int y1, int y2) { + firstB = x1; + firstE = x2; + secondB = y1; + secondE = y2; + } + } + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + public MatchingBlockScanner(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public MatchingBlockScanner(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 108) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return <code>false</code>, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length-zzEndRead); + + if (numRead > 0) { + zzEndRead+= numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * <b>cannot</b> be reused (internal buffer is discarded and lost). + * Lexical state is set to <tt>ZZ_INITIAL</tt>. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position <tt>pos</tt> from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public int yylex() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + zzInput = zzCMapL[zzInput]; + + boolean zzIsFinal = false; + boolean zzNoLookAhead = false; + + zzForNext: { switch (zzState) { + case 1: + switch (zzInput) { + case 0: + case 1: + case 3: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + case 2: zzIsFinal = true; zzState = 8; break zzForNext; + case 4: zzIsFinal = true; zzState = 9; break zzForNext; + case 5: zzIsFinal = true; zzState = 10; break zzForNext; + case 7: + case 8: zzIsFinal = true; zzState = 12; break zzForNext; + case 9: zzIsFinal = true; zzState = 13; break zzForNext; + case 10: zzIsFinal = true; zzState = 14; break zzForNext; + case 11: zzIsFinal = true; zzState = 15; break zzForNext; + case 14: zzIsFinal = true; zzState = 16; break zzForNext; + case 17: zzIsFinal = true; zzState = 17; break zzForNext; + case 18: zzIsFinal = true; zzState = 18; break zzForNext; + case 20: zzIsFinal = true; zzState = 19; break zzForNext; + case 24: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + default: zzIsFinal = true; zzState = 11; break zzForNext; + } + + case 2: + switch (zzInput) { + case 0: + case 2: + case 3: + case 5: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + case 8: zzIsFinal = true; zzState = 12; break zzForNext; + case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + case 1: zzIsFinal = true; zzState = 21; break zzForNext; + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 23; break zzForNext; + case 11: zzIsFinal = true; zzState = 24; break zzForNext; + case 13: zzIsFinal = true; zzState = 25; break zzForNext; + case 17: zzIsFinal = true; zzState = 26; break zzForNext; + case 20: zzIsFinal = true; zzState = 27; break zzForNext; + case 21: zzIsFinal = true; zzState = 28; break zzForNext; + case 23: zzIsFinal = true; zzState = 29; break zzForNext; + case 24: zzIsFinal = true; zzNoLookAhead = true; zzState = 30; break zzForNext; + case 25: zzIsFinal = true; zzState = 31; break zzForNext; + default: zzIsFinal = true; zzState = 22; break zzForNext; + } + + case 3: + switch (zzInput) { + case 24: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + case 10: zzIsFinal = true; zzState = 32; break zzForNext; + case 11: zzIsFinal = true; zzState = 33; break zzForNext; + case 14: zzIsFinal = true; zzState = 34; break zzForNext; + case 17: zzIsFinal = true; zzState = 35; break zzForNext; + case 18: zzIsFinal = true; zzState = 36; break zzForNext; + case 20: zzIsFinal = true; zzState = 37; break zzForNext; + default: zzIsFinal = true; zzNoLookAhead = true; zzState = 30; break zzForNext; + } + + case 4: + switch (zzInput) { + case 9: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 24: zzIsFinal = true; zzNoLookAhead = true; zzState = 30; break zzForNext; + case 23: zzIsFinal = true; zzState = 39; break zzForNext; + case 25: zzIsFinal = true; zzState = 40; break zzForNext; + default: zzIsFinal = true; zzState = 38; break zzForNext; + } + + case 5: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 41; break zzForNext; + default: break zzForAction; + } + + case 6: + switch (zzInput) { + default: zzIsFinal = true; zzNoLookAhead = true; zzState = 42; break zzForNext; + } + + case 8: + switch (zzInput) { + case 2: zzState = 43; break zzForNext; + default: break zzForAction; + } + + case 9: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 17: zzState = 45; break zzForNext; + default: break zzForAction; + } + + case 10: + switch (zzInput) { + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; break zzForNext; + } + + case 11: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 12: + switch (zzInput) { + case 7: + case 8: zzIsFinal = true; zzState = 47; break zzForNext; + case 1: + case 3: break zzForAction; + default: zzState = 46; break zzForNext; + } + + case 13: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + default: break zzForAction; + } + + case 14: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 11: zzIsFinal = true; zzState = 48; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 15: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 12: zzIsFinal = true; zzState = 49; break zzForNext; + case 22: zzIsFinal = true; zzState = 50; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 16: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 15: zzIsFinal = true; zzState = 51; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 17: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 23: zzIsFinal = true; zzState = 52; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 18: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 17: zzIsFinal = true; zzState = 53; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 19: + switch (zzInput) { + case 7: zzIsFinal = true; zzNoLookAhead = true; zzState = 44; break zzForNext; + case 13: zzIsFinal = true; zzState = 54; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 21: + switch (zzInput) { + case 2: zzState = 56; break zzForNext; + case 1: + case 3: break zzForAction; + default: zzState = 55; break zzForNext; + } + + case 22: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + default: break zzForAction; + } + + case 24: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 10: zzIsFinal = true; zzState = 64; break zzForNext; + default: break zzForAction; + } + + case 25: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 12: zzState = 65; break zzForNext; + default: break zzForAction; + } + + case 26: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 16: zzState = 66; break zzForNext; + default: break zzForAction; + } + + case 27: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 19: zzState = 67; break zzForNext; + default: break zzForAction; + } + + case 28: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 13: zzState = 68; break zzForNext; + default: break zzForAction; + } + + case 29: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 23: zzState = 62; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 12: zzState = 69; break zzForNext; + default: break zzForAction; + } + + case 31: + switch (zzInput) { + case 11: zzState = 57; break zzForNext; + case 13: zzState = 58; break zzForNext; + case 17: zzState = 59; break zzForNext; + case 20: zzState = 60; break zzForNext; + case 21: zzState = 61; break zzForNext; + case 25: zzState = 63; break zzForNext; + case 23: zzState = 70; break zzForNext; + default: break zzForAction; + } + + case 32: + switch (zzInput) { + case 11: zzIsFinal = true; zzState = 71; break zzForNext; + default: break zzForAction; + } + + case 33: + switch (zzInput) { + case 12: zzState = 72; break zzForNext; + case 22: zzState = 73; break zzForNext; + default: break zzForAction; + } + + case 34: + switch (zzInput) { + case 15: zzState = 74; break zzForNext; + default: break zzForAction; + } + + case 35: + switch (zzInput) { + case 16: zzState = 75; break zzForNext; + default: break zzForAction; + } + + case 36: + switch (zzInput) { + case 17: zzState = 76; break zzForNext; + default: break zzForAction; + } + + case 37: + switch (zzInput) { + case 13: zzState = 77; break zzForNext; + default: break zzForAction; + } + + case 38: + switch (zzInput) { + case 23: zzState = 78; break zzForNext; + case 25: zzState = 79; break zzForNext; + default: break zzForAction; + } + + case 39: + switch (zzInput) { + case 23: zzState = 78; break zzForNext; + case 25: zzState = 79; break zzForNext; + case 12: zzState = 80; break zzForNext; + default: break zzForAction; + } + + case 40: + switch (zzInput) { + case 25: zzState = 79; break zzForNext; + case 23: zzState = 81; break zzForNext; + default: break zzForAction; + } + + case 43: + switch (zzInput) { + case 1: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForNext; + } + + case 45: + switch (zzInput) { + case 23: zzState = 82; break zzForNext; + default: break zzForAction; + } + + case 46: + switch (zzInput) { + case 7: + case 8: zzIsFinal = true; zzState = 47; break zzForNext; + case 1: + case 3: break zzForAction; + default: break zzForNext; + } + + case 47: + switch (zzInput) { + case 7: + case 8: zzState = 46; break zzForNext; + default: break zzForAction; + } + + case 48: + switch (zzInput) { + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 49: + switch (zzInput) { + case 13: zzIsFinal = true; zzState = 48; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 50: + switch (zzInput) { + case 23: zzIsFinal = true; zzState = 83; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 51: + switch (zzInput) { + case 10: zzIsFinal = true; zzState = 84; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 52: + switch (zzInput) { + case 25: zzIsFinal = true; zzState = 85; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 53: + switch (zzInput) { + case 16: zzIsFinal = true; zzState = 86; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 54: + switch (zzInput) { + case 21: zzIsFinal = true; zzState = 48; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 55: + switch (zzInput) { + case 2: zzState = 56; break zzForNext; + case 1: + case 3: break zzForAction; + default: break zzForNext; + } + + case 56: + switch (zzInput) { + case 2: zzIsFinal = true; zzState = 87; break zzForNext; + case 1: + case 3: break zzForAction; + default: zzState = 55; break zzForNext; + } + + case 57: + switch (zzInput) { + case 10: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 58: + switch (zzInput) { + case 12: zzState = 88; break zzForNext; + default: break zzForAction; + } + + case 59: + switch (zzInput) { + case 16: zzState = 89; break zzForNext; + default: break zzForAction; + } + + case 60: + switch (zzInput) { + case 19: zzState = 90; break zzForNext; + default: break zzForAction; + } + + case 61: + switch (zzInput) { + case 13: zzState = 91; break zzForNext; + default: break zzForAction; + } + + case 62: + switch (zzInput) { + case 12: zzState = 92; break zzForNext; + default: break zzForAction; + } + + case 63: + switch (zzInput) { + case 23: zzState = 93; break zzForNext; + default: break zzForAction; + } + + case 64: + switch (zzInput) { + case 17: zzIsFinal = true; zzState = 94; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + } + + case 65: + switch (zzInput) { + case 11: zzIsFinal = true; zzState = 95; break zzForNext; + default: break zzForAction; + } + + case 66: + switch (zzInput) { + case 10: zzState = 96; break zzForNext; + default: break zzForAction; + } + + case 67: + switch (zzInput) { + case 17: zzState = 97; break zzForNext; + default: break zzForAction; + } + + case 68: + switch (zzInput) { + case 12: zzState = 88; break zzForNext; + case 20: zzIsFinal = true; zzState = 95; break zzForNext; + default: break zzForAction; + } + + case 69: + switch (zzInput) { + case 10: zzState = 98; break zzForNext; + default: break zzForAction; + } + + case 70: + switch (zzInput) { + case 17: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + case 12: zzState = 92; break zzForNext; + default: break zzForAction; + } + + case 71: + switch (zzInput) { + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 99; break zzForNext; + } + + case 72: + switch (zzInput) { + case 13: zzIsFinal = true; zzState = 71; break zzForNext; + default: break zzForAction; + } + + case 73: + switch (zzInput) { + case 23: zzState = 100; break zzForNext; + default: break zzForAction; + } + + case 74: + switch (zzInput) { + case 10: zzState = 101; break zzForNext; + default: break zzForAction; + } + + case 75: + switch (zzInput) { + case 18: zzState = 102; break zzForNext; + default: break zzForAction; + } + + case 76: + switch (zzInput) { + case 16: zzState = 103; break zzForNext; + default: break zzForAction; + } + + case 77: + switch (zzInput) { + case 21: zzIsFinal = true; zzState = 71; break zzForNext; + default: break zzForAction; + } + + case 78: + switch (zzInput) { + case 12: zzState = 104; break zzForNext; + default: break zzForAction; + } + + case 79: + switch (zzInput) { + case 23: zzState = 105; break zzForNext; + default: break zzForAction; + } + + case 80: + switch (zzInput) { + case 10: zzState = 106; break zzForNext; + default: break zzForAction; + } + + case 81: + switch (zzInput) { + case 17: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + case 12: zzState = 104; break zzForNext; + default: break zzForAction; + } + + case 82: + switch (zzInput) { + case 25: zzIsFinal = true; zzState = 107; break zzForNext; + default: break zzForAction; + } + + case 83: + switch (zzInput) { + case 19: zzIsFinal = true; zzState = 108; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 84: + switch (zzInput) { + case 16: zzIsFinal = true; zzState = 109; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 85: + switch (zzInput) { + case 11: zzIsFinal = true; zzState = 110; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 86: + switch (zzInput) { + case 17: zzIsFinal = true; zzState = 111; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 87: + switch (zzInput) { + case 2: zzIsFinal = true; break zzForNext; + case 1: + case 3: break zzForAction; + default: zzState = 55; break zzForNext; + } + + case 88: + switch (zzInput) { + case 11: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 89: + switch (zzInput) { + case 10: zzState = 112; break zzForNext; + default: break zzForAction; + } + + case 90: + switch (zzInput) { + case 17: zzState = 113; break zzForNext; + default: break zzForAction; + } + + case 91: + switch (zzInput) { + case 20: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 92: + switch (zzInput) { + case 10: zzState = 114; break zzForNext; + default: break zzForAction; + } + + case 93: + switch (zzInput) { + case 17: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 94: + switch (zzInput) { + case 18: zzState = 115; break zzForNext; + default: break zzForAction; + } + + case 95: + switch (zzInput) { + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + } + + case 96: + switch (zzInput) { + case 15: zzState = 116; break zzForNext; + default: break zzForAction; + } + + case 97: + switch (zzInput) { + case 16: zzState = 117; break zzForNext; + default: break zzForAction; + } + + case 98: + switch (zzInput) { + case 20: zzState = 118; break zzForNext; + default: break zzForAction; + } + + case 99: + switch (zzInput) { + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; break zzForNext; + } + + case 100: + switch (zzInput) { + case 19: zzState = 119; break zzForNext; + default: break zzForAction; + } + + case 101: + switch (zzInput) { + case 16: zzState = 120; break zzForNext; + default: break zzForAction; + } + + case 102: + switch (zzInput) { + case 17: zzIsFinal = true; zzState = 121; break zzForNext; + default: break zzForAction; + } + + case 103: + switch (zzInput) { + case 17: zzState = 122; break zzForNext; + default: break zzForAction; + } + + case 104: + switch (zzInput) { + case 10: zzState = 123; break zzForNext; + default: break zzForAction; + } + + case 105: + switch (zzInput) { + case 17: zzIsFinal = true; zzNoLookAhead = true; zzState = 30; break zzForNext; + default: break zzForAction; + } + + case 106: + switch (zzInput) { + case 20: zzState = 124; break zzForNext; + default: break zzForAction; + } + + case 107: + switch (zzInput) { + case 11: zzState = 125; break zzForNext; + default: break zzForAction; + } + + case 108: + switch (zzInput) { + case 20: zzIsFinal = true; zzState = 126; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 109: + switch (zzInput) { + case 17: zzIsFinal = true; zzState = 48; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 110: + switch (zzInput) { + case 22: zzIsFinal = true; zzState = 127; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 111: + switch (zzInput) { + case 19: zzIsFinal = true; zzState = 128; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 112: + switch (zzInput) { + case 15: zzState = 129; break zzForNext; + default: break zzForAction; + } + + case 113: + switch (zzInput) { + case 16: zzState = 130; break zzForNext; + default: break zzForAction; + } + + case 114: + switch (zzInput) { + case 20: zzState = 131; break zzForNext; + default: break zzForAction; + } + + case 115: + switch (zzInput) { + case 16: zzState = 93; break zzForNext; + default: break zzForAction; + } + + case 116: + switch (zzInput) { + case 14: zzIsFinal = true; zzState = 95; break zzForNext; + default: break zzForAction; + } + + case 117: + switch (zzInput) { + case 17: zzState = 132; break zzForNext; + default: break zzForAction; + } + + case 118: + switch (zzInput) { + case 19: zzState = 133; break zzForNext; + default: break zzForAction; + } + + case 119: + switch (zzInput) { + case 20: zzState = 134; break zzForNext; + default: break zzForAction; + } + + case 120: + switch (zzInput) { + case 17: zzIsFinal = true; zzState = 71; break zzForNext; + default: break zzForAction; + } + + case 121: + switch (zzInput) { + case 10: zzState = 135; break zzForNext; + default: break zzForAction; + } + + case 122: + switch (zzInput) { + case 19: zzState = 136; break zzForNext; + default: break zzForAction; + } + + case 123: + switch (zzInput) { + case 20: zzState = 137; break zzForNext; + default: break zzForAction; + } + + case 124: + switch (zzInput) { + case 19: zzState = 138; break zzForNext; + default: break zzForAction; + } + + case 125: + switch (zzInput) { + case 22: zzState = 139; break zzForNext; + default: break zzForAction; + } + + case 126: + switch (zzInput) { + case 10: zzIsFinal = true; zzState = 140; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 127: + switch (zzInput) { + case 23: zzIsFinal = true; zzState = 141; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 128: + switch (zzInput) { + case 20: zzIsFinal = true; zzState = 48; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 129: + switch (zzInput) { + case 14: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 130: + switch (zzInput) { + case 17: zzState = 142; break zzForNext; + default: break zzForAction; + } + + case 131: + switch (zzInput) { + case 19: zzState = 143; break zzForNext; + default: break zzForAction; + } + + case 132: + switch (zzInput) { + case 18: zzIsFinal = true; zzState = 95; break zzForNext; + default: break zzForAction; + } + + case 133: + switch (zzInput) { + case 23: zzState = 144; break zzForNext; + default: break zzForAction; + } + + case 134: + switch (zzInput) { + case 10: zzState = 145; break zzForNext; + default: break zzForAction; + } + + case 135: + switch (zzInput) { + case 11: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + default: break zzForAction; + } + + case 136: + switch (zzInput) { + case 20: zzIsFinal = true; zzState = 71; break zzForNext; + default: break zzForAction; + } + + case 137: + switch (zzInput) { + case 19: zzState = 146; break zzForNext; + default: break zzForAction; + } + + case 138: + switch (zzInput) { + case 23: zzState = 147; break zzForNext; + default: break zzForAction; + } + + case 139: + switch (zzInput) { + case 23: zzState = 148; break zzForNext; + default: break zzForAction; + } + + case 140: + switch (zzInput) { + case 12: zzIsFinal = true; zzState = 149; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 141: + switch (zzInput) { + case 19: zzIsFinal = true; zzState = 150; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 142: + switch (zzInput) { + case 18: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 143: + switch (zzInput) { + case 23: zzState = 151; break zzForNext; + default: break zzForAction; + } + + case 144: + switch (zzInput) { + case 22: zzState = 152; break zzForNext; + default: break zzForAction; + } + + case 145: + switch (zzInput) { + case 12: zzState = 153; break zzForNext; + default: break zzForAction; + } + + case 146: + switch (zzInput) { + case 23: zzState = 154; break zzForNext; + default: break zzForAction; + } + + case 147: + switch (zzInput) { + case 22: zzState = 155; break zzForNext; + default: break zzForAction; + } + + case 148: + switch (zzInput) { + case 19: zzState = 156; break zzForNext; + default: break zzForAction; + } + + case 149: + switch (zzInput) { + case 23: zzIsFinal = true; zzState = 48; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 150: + switch (zzInput) { + case 20: zzIsFinal = true; zzState = 157; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 151: + switch (zzInput) { + case 22: zzState = 158; break zzForNext; + default: break zzForAction; + } + + case 152: + switch (zzInput) { + case 11: zzIsFinal = true; zzState = 159; break zzForNext; + default: break zzForAction; + } + + case 153: + switch (zzInput) { + case 23: zzIsFinal = true; zzState = 71; break zzForNext; + default: break zzForAction; + } + + case 154: + switch (zzInput) { + case 22: zzState = 160; break zzForNext; + default: break zzForAction; + } + + case 155: + switch (zzInput) { + case 11: zzState = 161; break zzForNext; + default: break zzForAction; + } + + case 156: + switch (zzInput) { + case 20: zzState = 162; break zzForNext; + default: break zzForAction; + } + + case 157: + switch (zzInput) { + case 10: zzIsFinal = true; zzState = 163; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 158: + switch (zzInput) { + case 11: zzIsFinal = true; zzState = 164; break zzForNext; + default: break zzForAction; + } + + case 159: + switch (zzInput) { + case 25: zzIsFinal = true; zzState = 165; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + } + + case 160: + switch (zzInput) { + case 11: zzState = 166; break zzForNext; + default: break zzForAction; + } + + case 161: + switch (zzInput) { + case 25: zzState = 167; break zzForNext; + default: break zzForAction; + } + + case 162: + switch (zzInput) { + case 10: zzState = 168; break zzForNext; + default: break zzForAction; + } + + case 163: + switch (zzInput) { + case 12: zzIsFinal = true; zzState = 169; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 164: + switch (zzInput) { + case 25: zzState = 63; break zzForNext; + default: break zzForAction; + } + + case 165: + switch (zzInput) { + case 23: zzState = 170; break zzForNext; + default: break zzForAction; + } + + case 166: + switch (zzInput) { + case 25: zzState = 79; break zzForNext; + default: break zzForAction; + } + + case 167: + switch (zzInput) { + case 23: zzState = 170; break zzForNext; + default: break zzForAction; + } + + case 168: + switch (zzInput) { + case 12: zzState = 171; break zzForNext; + default: break zzForAction; + } + + case 169: + switch (zzInput) { + case 23: zzIsFinal = true; zzState = 172; break zzForNext; + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + case 170: + switch (zzInput) { + case 17: zzIsFinal = true; zzNoLookAhead = true; zzState = 20; break zzForNext; + default: break zzForAction; + } + + case 171: + switch (zzInput) { + case 23: zzIsFinal = true; zzNoLookAhead = true; zzState = 7; break zzForNext; + default: break zzForAction; + } + + case 172: + switch (zzInput) { + case 0: + case 1: + case 2: + case 3: + case 5: + case 7: + case 8: + case 9: + case 24: break zzForAction; + default: zzIsFinal = true; zzState = 10; break zzForNext; + } + + default: + // if this is ever reached, there is a serious bug in JFlex + zzScanError(ZZ_UNKNOWN_ERROR); + break; + } } + + if ( zzIsFinal ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( zzNoLookAhead ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 7: + { char c = yycharat(yylength() - 2); + if (c == ')' || c == ']' || c == '}') { + transp = true; + return 0; + } + } + case 8: break; + case 5: + { if (scilabLexer.getKeyword(start - yychar, false) == ScilabLexerConstants.STRING) { + savePos = start - yychar - scilabLexer.beginString - scilabLexer.start; + yybegin(SPEC); + } else { + yybegin(RL); + } + } + case 9: break; + case 4: + { yypushback(1); + yybegin(PSNART); + } + case 10: break; + case 2: + { return 0; + } + case 11: break; + case 6: + { if (--savePos == 0) { + yybegin(RL); + } + } + case 12: break; + case 3: + { return 1; + } + case 13: break; + case 1: + { + } + case 14: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { return -1; + } + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotes.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotes.java new file mode 100755 index 000000000..adde0f2aa --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotes.java @@ -0,0 +1,2641 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.UUID; +import java.util.logging.Logger; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JSplitPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.EditorKit; +import javax.swing.text.View; +import javax.swing.undo.UndoManager; + +import org.w3c.dom.Document; + +import org.flexdock.docking.event.DockingEvent; +import org.scilab.modules.commons.CommonFileUtils; +import org.scilab.modules.commons.gui.ScilabKeyStroke; +import org.scilab.modules.commons.xml.ScilabXMLUtilities; +import org.scilab.modules.commons.xml.XConfiguration; +import static org.scilab.modules.commons.xml.XConfiguration.XConfAttribute; +import org.scilab.modules.core.Scilab; +import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser; +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.bridge.window.SwingScilabWindow; +import org.scilab.modules.gui.filechooser.Juigetfile; +import org.scilab.modules.gui.filechooser.ScilabFileChooser; +import org.scilab.modules.gui.menubar.MenuBar; +import org.scilab.modules.gui.messagebox.MessageBox; +import org.scilab.modules.gui.messagebox.ScilabMessageBox; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.gui.tab.SimpleTab; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; +import org.scilab.modules.gui.textbox.TextBox; +import org.scilab.modules.gui.toolbar.ToolBar; +import org.scilab.modules.gui.utils.ClosingOperationsManager; +import org.scilab.modules.gui.utils.ConfigManager; +import org.scilab.modules.gui.utils.Position; +import org.scilab.modules.gui.utils.SciFileFilter; +import org.scilab.modules.gui.utils.Size; +import org.scilab.modules.gui.utils.WindowsConfigurationManager; + +import org.scilab.modules.scinotes.actions.DoubleQuoteStringAction; +import org.scilab.modules.scinotes.actions.EncodingAction; +import org.scilab.modules.scinotes.actions.EndOfLineAction; +import org.scilab.modules.scinotes.actions.ExitAction; +import org.scilab.modules.scinotes.actions.FindAction; +import org.scilab.modules.scinotes.actions.IncrementalSearchAction; +import org.scilab.modules.scinotes.actions.IndentAction; +import org.scilab.modules.scinotes.actions.InsertOverwriteAction; +import org.scilab.modules.scinotes.actions.LineBeautifierAction; +import org.scilab.modules.scinotes.actions.OpenSourceFileOnKeywordAction; +import org.scilab.modules.scinotes.actions.RecentFileAction; +import org.scilab.modules.scinotes.actions.RegisterFavoriteDirsAction; +import org.scilab.modules.scinotes.actions.RemoveTrailingWhiteAction; +import org.scilab.modules.scinotes.actions.RestoreOpenedFilesAction; +import org.scilab.modules.scinotes.actions.SciNotesCompletionAction; +import org.scilab.modules.scinotes.actions.SearchWordInFilesAction; +import org.scilab.modules.scinotes.tabfactory.CodeNavigatorTab; +import org.scilab.modules.scinotes.tabfactory.SciNotesTab; +import org.scilab.modules.scinotes.tabfactory.SciNotesTabFactory; +import org.scilab.modules.scinotes.tabfactory.SearchInFilesTab; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.DropFilesListener; +import org.scilab.modules.scinotes.utils.NavigatorWindow; +import org.scilab.modules.scinotes.utils.SaveFile; +import org.scilab.modules.scinotes.utils.SciNotesContents; +import org.scilab.modules.scinotes.utils.SciNotesMessages; +import org.scilab.modules.scinotes.utils.ScilabTabbedPane; +import org.scilab.modules.scinotes.utils.SearchFile; + +/** + * Main SciNotes class. + * + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public class SciNotes extends SwingScilabDockablePanel { + + private static final long serialVersionUID = -6410183357490518676L; + + private static final String XPATH_SCINOTES_KEY = "//general/shortcuts/body/actions/action-folder[@name='Scinotes']/action"; + private static final String XPATH_SCINOTES_ACTION = "/map/scinotes/entry"; + + private static final String SCINOTES = "SciNotes"; + private static final String SCI_EXTENSION = ".sci"; + private static final String SCE_EXTENSION = ".sce"; + private static final String TST_EXTENSION = ".tst"; + private static final String QUIT_EXTENSION = ".quit"; + private static final String DEM_EXTENSION = ".dem"; + private static final String START_EXTENSION = ".start"; + private static final String ALL_TST_FILES = "*.tst"; + private static final String ALL_QUIT_FILES = "*.quit"; + private static final String ALL_START_FILES = "*.start"; + private static final String ALL_SCI_FILES = "*.sci"; + private static final String ALL_SCE_FILES = "*.sce"; + private static final String ALL_DEM_FILES = "*.dem"; + private static final String ALL_SCX_FILES = "*.sc*"; + private static final String ALL_SCILAB = "all"; + private static final String ALL_FILES = "*.*"; + private static final String DOT = "."; + + private static final String DEFAULTACTIONPATH = "org.scilab.modules.scinotes.actions"; + + private static final Map<String, String> actionToName; + private static Map<String, KeyStroke> actionKeys; + + private static List<SciNotes> scinotesList = new ArrayList<SciNotes>(); + private static SciNotes editor; + private static boolean mustWrapLines; + + private SwingScilabWindow parentWindow; + private UUID uuid; + + private ScilabTabbedPane tabPane; + private final SciNotesContents contentPane; + private NavigatorWindow navigator; + private SearchFile searchInFiles; + + private int numberOfUntitled; + private EditorKit editorKit; + + private JButton undoButton; + private JButton redoButton; + + private boolean protectOpenFileList; + private boolean restored; + private boolean firstOpen = true; + + private final List<Integer> tabList = new ArrayList<Integer>(); + private final List<Integer> closedTabList = new ArrayList<Integer>(); + + static { + ConfigSciNotesManager.createUserCopy(); + ScilabTabFactory.getInstance().addTabFactory(SciNotesTabFactory.getInstance()); + Scilab.registerInitialHook(new Runnable() { + @Override + public void run() { + updateSciNotes(); + } + }); + + Document doc = ScilabXMLUtilities.readDocument(System.getenv("SCI") + "/modules/console/etc/Actions-Configuration.xml"); + actionToName = XConfiguration.get(doc, "name", String.class, "action", String.class, XPATH_SCINOTES_ACTION); + XConfiguration.addXConfigurationListener(new SciNotesConfiguration()); + } + + /** + * Create SciNotes instance + */ + public SciNotes(String uuid) { + super(SCINOTES, uuid); + setWindowIcon("accessories-text-editor"); + setAssociatedXMLIDForHelp("scinotes"); + this.uuid = UUID.fromString(uuid); + SciNotesAutosave.autosave(); + editor = this; + scinotesList.add(this); + numberOfUntitled = 0; + mustWrapLines = SciNotesOptions.getSciNotesDisplay().wrapLines; + editorKit = new ScilabEditorKit(!mustWrapLines); + protectOpenFileList = false; + contentPane = new SciNotesContents(this); + tabPane = contentPane.getScilabTabbedPane(); + tabPane.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (getTextPane() != null) { + // updateUI(); + getTextPane().updateInfosWhenFocused(); + getTextPane().requestFocus(); + getTextPane().highlightWords(IncrementalSearchAction.getWord(SciNotes.this), IncrementalSearchAction.getExact(SciNotes.this)); + + // Update encoding menu + EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument()); + + // Update End Of Line menu + EndOfLineAction.updateEolMenu((ScilabDocument) getTextPane().getDocument()); + setTitle(getTextPane().getTitle()); + } + } + }); + this.setContentPane(contentPane); + } + + /** + * Default constructor + */ + public SciNotes() { + this(UUID.randomUUID().toString()); + } + + public static void configurationChanged(SciNotesConfiguration.Conf conf) { + setWhereamiLineNumbering(); + setAutoIndent(); + setHorizontalWrap(); + setDefaultTabulation(); + if (conf.keymap) { + actionKeys = null; + setKeyStrokeActions(); + setAllMenus(); + } + if (conf.autosave) { + SciNotesAutosave.stopAutosave(); + SciNotesAutosave.autosave(); + } + if (conf.preferences) { + RecentFileAction.updateRecentOpenedFilesMenu(); + } + + updatePanes(conf); + } + + public static Map<String, KeyStroke> getActionKeys() { + if (actionKeys == null) { + Document doc = XConfiguration.getXConfigurationDocument(); + actionKeys = XConfiguration.get(doc, "name", String.class, "key", KeyStroke.class, XPATH_SCINOTES_KEY); + } + + return actionKeys; + } + + public static Map<String, String> getActionName() { + return actionToName; + } + + /** + * Get an opened editor from its uuid + * + * @param uuid + * the uuid + * @return the corresponding editor + */ + public static SciNotes getEditorFromUUID(String uuid) { + for (SciNotes ed : scinotesList) { + if (ed.getPersistentId().equals(uuid)) { + return ed; + } + } + + return null; + } + + public void setParentWindow() { + this.parentWindow = SwingScilabWindow.createWindow(true); + parentWindow.setLocation(150, 50); + parentWindow.setSize(650, 550); + } + + /** + * {@inheritDoc} + */ + @Override + public void setTitle(String title) { + super.setTitle(title); + SwingScilabWindow window = (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, tabPane); + if (window != null) { + window.setTitle(title); + } + } + + public void insertBottomComponent(Component c) { + contentPane.insertBottomComponent(c); + } + + /** + * @return the SwingScilabWindow containing this editor + */ + public SwingScilabWindow getSwingParentWindow() { + return (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this); + } + + /** + * {@inheritDoc} + */ + @Override + public void undockingComplete(DockingEvent evt) { + super.undockingComplete(evt); + if (navigator != null) { + navigator.addToolBar(null); + } + if (searchInFiles != null) { + searchInFiles.addToolBar(null); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void dockingComplete(DockingEvent evt) { + super.dockingComplete(evt); + if (navigator != null) { + navigator.changeToolBar(); + } + if (searchInFiles != null) { + searchInFiles.changeToolBar(); + } + } + + /** + * Add a code navigator + */ + public void addNavigator() { + if (navigator == null) { + String navUUID = ConfigSciNotesManager.getCodeNavigatorStateForEditor(getPersistentId()); + boolean success = WindowsConfigurationManager.restoreUUID(navUUID); + if (!success) { + navigator = CodeNavigatorTab.getCodeNavigatorInstance(this, null); + navigator.setParentWindow(); + } + int count = getTabPane().getTabCount(); + for (int i = 0; i < count; i++) { + navigator.addEditorPane(getTextPane(i)); + } + } + } + + /** + * Add a code navigator + */ + public void addNavigator(NavigatorWindow navigator) { + this.navigator = navigator; + } + + /** + * Remove the navigator + */ + public void removeNavigator() { + navigator = null; + } + + /** + * @return the navigator associated with this editor + */ + public NavigatorWindow getNavigator() { + return navigator; + } + + /** + * Add a Search in files + */ + public void addSearchInFiles() { + if (searchInFiles == null) { + String sfUUID = ConfigSciNotesManager.getSearchInFilesStateForEditor(getPersistentId()); + boolean success = WindowsConfigurationManager.restoreUUID(sfUUID); + if (!success) { + searchInFiles = SearchInFilesTab.getSearchInFilesTabInstance(this, null); + searchInFiles.setParentWindow(); + } + } + } + + /** + * Add a Search In Files + */ + public void addSearchInFiles(SearchFile sf) { + this.searchInFiles = sf; + } + + /** + * Remove Search in Files + */ + public void removeSearchInFiles() { + searchInFiles = null; + } + + /** + * @return the Search In Files associated with this editor + */ + public SearchFile getSearchInFiles() { + return searchInFiles; + } + + /** + * Update the editor + */ + public static void updateSciNotes() { + ScilabLexer.update(); + for (SciNotes editor : scinotesList) { + if (editor.getTextPane() != null) { + editor.getTextPane().repaint(); + } + } + } + + /** + * Launch SciNotes with an empty file + * + * This method *must not* be called on the EDT thread. + */ + public static void scinotes() { + ScilabLexer.update(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + launchSciNotes(); + // Open an empty file if no tabs were opened at launch. + if (editor.getTabPane().getTabCount() == 0) { + editor.openFile(null, 0, null); + } + } + }); + } catch (InterruptedException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + /** + * Launch SciNotes with a file name to open. + * + * @param filePath + * the name of the file to open + * + * This method *must not* be called on the EDT thread. + */ + public static void scinotes(final String filePath) { + ScilabLexer.update(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + launchSciNotes(); + editor.openFile(filePath, 0, null); + } + }); + } catch (InterruptedException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } + } + + /** + * Launch SciNotes with a file name to open and a line to highlight. + * + * @param filePath + * the name of the file to open + * @param lineNumber + * the line to highlight + * + * This method *must not* be called on the EDT thread. + */ + public static void scinotes(final String filePath, final int lineNumber, final String functionName) { + ScilabLexer.update(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + launchSciNotes(); + editor.openFile(filePath, lineNumber, functionName); + } + }); + } catch (InterruptedException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } + } + + /** + * Launch SciNotes with a file name to open and a line to highlight. + * + * @param filePath + * the name of the file to open + * @param option + * such as 'readonly' + * + * This method *must not* be called on the EDT thread. + */ + public static void scinotes(final String filePath, final String[] options) throws Exception { + boolean hasAction = false; + if (options != null && options.length != 0) { + try { + hasAction = executeAction(filePath, options); + } catch (FileNotFoundException e) { + throw new Exception(String.format(SciNotesMessages.INVALID_FILE, filePath)); + } catch (IOException e) { + throw new Exception(String.format(SciNotesMessages.IO_EXCEPTION, e.getLocalizedMessage())); + } + } + + if (hasAction) { + return; + } + + ScilabLexer.update(); + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + launchSciNotes(); + if (options != null && options.length != 0) { + editor.openFile(filePath, 0, options[0]); + } else { + editor.openFile(filePath, 0, ""); + } + } + }); + } catch (InterruptedException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + e.printStackTrace(); + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } + } + + /** + * Launch SciNotes with a provided text (from the help for example). + * + * @param text + * the text which should be modified + */ + public static void scinotesWithText(String text) { + ScilabLexer.update(); + launchSciNotes(); + ScilabEditorPane theTextPane; + if (editor.getTabPane().getTabCount() != 0 && editor.getTextPane(0) != null) { + String name = editor.getTextPane(0).getName(); + if (name == null) { + theTextPane = editor.getTextPane(0); + } else { + theTextPane = editor.addEmptyTab(); + } + } else { + theTextPane = editor.addEmptyTab(); + } + + ScilabDocument styleDocument = (ScilabDocument) theTextPane.getDocument(); + try { + editor.getEditorKit().read(new StringReader(text), styleDocument, theTextPane.getCaretPosition()); + } catch (IOException e) { + System.err.println(SciNotesMessages.ERROR_WITH_STRING); + } catch (BadLocationException e) { + System.err.println(SciNotesMessages.ERROR_WITH_STRING); + } + } + + /** + * Clone the current tab and if b is true close the tab + * + * @param ed + * the editor where the tab is + * @param b + * a boolean + */ + public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b) { + ScilabDocument cdoc = (ScilabDocument) ed.getTextPane().getDocument(); + String title = ed.getTabPane().getScilabTitleAt(ed.getTabPane().getSelectedIndex()); + ScilabEditorPane currentSep = ed.getTextPane(); + String winTitle = ed.getTitle(); + + if (b) { + ed.closeTabAtWithoutConfirmation(ed.getTabPane().getSelectedIndex()); + if (ed.getTabPane().getTabCount() == 0) { + ClosingOperationsManager.startClosingOperationWithoutSave((SwingScilabDockablePanel) ed); + ConfigSciNotesManager.removeEditorUUID(ed.uuid.toString()); + } + } + + editor = null; + + scinotesWithText(cdoc.getText()); + ScilabEditorPane sep = editor.getTextPane(); + + if (currentSep.getName() != null) { + sep.setTitle(title); + editor.setTitle(winTitle); + } + + currentSep.copyProps(sep); + ScilabDocument sdoc = (ScilabDocument) sep.getDocument(); + sdoc.setContentModified(cdoc.isContentModified()); + sdoc.getUndoManager().discardAllEdits(); + sep.setCaretPosition(0); + editor.enableUndoButton(false); + editor.enableRedoButton(false); + ConfigSciNotesManager.saveToOpenFiles(sep.getName(), editor, editor.getTextPane()); + + editor.activeRestoreTab(); + } + + /** + * Clone the current tab and if b is true close the tab + * + * @param ed + * the editor where the tab is + * @param b + * a boolean + */ + public static void cloneAndCloseCurrentTab(SciNotes ed, boolean b, int x, int y) { + cloneAndCloseCurrentTab(ed, b); + editor.getSwingParentWindow().setLocation(x, y); + } + + /** + * Execute after when the restoration is finished + */ + @Override + public void endedRestoration() { + if (!SwingUtilities.isEventDispatchThread()) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + restorePreviousSession(); + } + }); + } catch (InterruptedException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + throw new RuntimeException(e); + } + } else { + restorePreviousSession(); + } + } + + /** + * Restore the previous session + */ + public void restorePreviousSession() { + restored = true; + if (!SciNotesOptions.getSciNotesPreferences().restartOpen || !ConfigSciNotesManager.getRestoreOpenedFiles() || ConfigSciNotesManager.countExistingOpenFiles(getUUID()) == 0) { + if (getTabPane().getTabCount() == 0) { + openFile(null, 0, null); + } + + WindowsConfigurationManager.restorationFinished(this); + + return; + } + + addRestoreTab(); + WindowsConfigurationManager.restorationFinished(SciNotes.this); + } + + /** + * Create SciNotes instance + * + * @return the instance + */ + public static void launchSciNotes() { + if (editor == null) { + List<String> uuids = ConfigSciNotesManager.getEditorsUUID(); + boolean success = false; + if (!uuids.isEmpty()) { + for (String uuid : uuids) { + boolean exists = false; + for (SciNotes ed : scinotesList) { + if (ed.uuid.toString().equals(uuid)) { + exists = true; + break; + } + } + if (!exists) { + success = WindowsConfigurationManager.restoreUUID(uuid); + if (success) { + break; + } + ConfigSciNotesManager.removeEditorUUID(uuid); + } + } + } + if (!success) { + editor = SciNotesTab.getEditorInstance(null); + editor.setParentWindow(); + ConfigSciNotesManager.saveEditorUUID(editor.getPersistentId()); + SciNotesGUI.init(editor.getParentWindow(), editor, SCINOTES); + WindowsConfigurationManager.unregisterEndedRestoration(editor); + } + } + + if (!editor.restored) { + editor.restorePreviousSession(); + } + } + + /** + * Open a file. + * + * This method *must* be called on the EDT thread. + * + * @param filePath + * the file path (may be null) + * @param lineNumber + * the line number (use 0 for unspecified) + * @param option + * the options (may be null) + */ + public void openFile(String filePath, int lineNumber, String option) { + if (!SwingUtilities.isEventDispatchThread()) { + throw new RuntimeException("called outside the EDT thread."); + } + + if (filePath == null) { + addEmptyTab(); + activeRestoreTab(); + return; + } + + File f = fileToCanonicalFile(new File(filePath)); + if (!f.getParentFile().exists()) { + JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.OPEN_ERROR); + addEmptyTab(); + activeRestoreTab(); + return; + } + + if (f.isDirectory()) { /* Bug 5131 */ + ConfigManager.saveLastOpenedDirectory(f.getPath()); + addEmptyTab(); + activeRestoreTab(); + return; + } + + readFileAndWait(f); + if (option == null || option.length() == 0 || "readonly".equals(option.toLowerCase())) { + getTextPane().scrollTextToLineNumber(lineNumber, true); + } else { + getTextPane().scrollTextToLineNumberInWhereami(lineNumber, option, true); + } + if ((option != null && "readonly".equals(option.toLowerCase()))) { + getTextPane().setReadOnly(true); + getInfoBar().setText(getTextPane().getInfoBarText()); + ConfigSciNotesManager.removeFromOpenFiles(this, getTextPane()); + } else { + ConfigSciNotesManager.saveToRecentOpenedFiles(filePath); + RecentFileAction.updateRecentOpenedFilesMenu(this); + } + + activeRestoreTab(); + } + + public void activeRestoreTab() { + if (getTextPane(0) == null) { + tabPane.setSelectedIndex(0); + getInfoBar().setText(""); + } + } + + /** + * Close SciNotes instance including all tabs. + */ + public void closeSciNotes() { + for (int i = 0; i < getTabPane().getTabCount(); i++) { + ScilabEditorPane textPaneAt = getTextPane(i); + if (textPaneAt != null) { + textPaneAt.destroy(); + } + } + + FindAction.close(); + IncrementalSearchAction.close(this); + RecentFileAction.close(this); + OpenSourceFileOnKeywordAction.closeOpenSourceWindow(); + SearchWordInFilesAction.closeWindow(); + + /* + * setProtectOpenFileList(true); while (getTabPane().getTabCount() > 0) + * { closeTabAt(0, true); } setProtectOpenFileList(false); + */ + + scinotesList.remove(this); + if (scinotesList.size() == 0) { + SciNotesAutosave.stopAutosave(); + ScilabEditorPane.clean(); + RegisterFavoriteDirsAction.close(); + OpenSourceFileOnKeywordAction.close(); + EncodingAction.close(); + EndOfLineAction.close(); + HelpOnTypingManager.close(); + } + + editor = null; + SciNotesGUI.clean(this); + close(); + ConfigSciNotesManager.resetDocument(); + } + + public boolean canClose() { + int numberOfTab = getTabPane().getTabCount(); + setProtectOpenFileList(true); + + for (int i = 0; i < numberOfTab; i++) { + boolean ans = checkToCloseTabAt(i); + if (!ans) { + setProtectOpenFileList(false); + return false; + } + } + setProtectOpenFileList(false); + + return true; + } + + public String askForClosing() { + int numberOfTab = getTabPane().getTabCount(); + boolean isContentModified = false; + for (int i = 0; i < getTabPane().getTabCount(); i++) { + ScilabEditorPane textPaneAt = getTextPane(i); + if (textPaneAt != null && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) { + isContentModified = true; + break; + } + } + + if (isContentModified) { + return "SciNotes"; + } + + return null; + } + + public static void closeEditor(SciNotes ed) { + if (scinotesList.size() > 1) { + ClosingOperationsManager.startClosingOperationWithoutSave((SwingScilabDockablePanel) ed); + } else { + ClosingOperationsManager.startClosingOperation((SwingScilabDockablePanel) ed); + } + } + + /** + * Close a tab using its index. + * + * @param indexTab + * the index of the tab + * @return if the tab has been really closed + */ + public boolean closeTabAtWithoutConfirmation(int indexTab) { + return closeTabAt(indexTab, false, false); + } + + /** + * Close a tab using its index. + * + * @param indexTab + * the index of the tab + * @return if the tab has been really closed + */ + public boolean closeTabAt(int indexTab) { + return closeTabAt(indexTab, false, true); + } + + /** + * Close a tab using its index. + * + * @param indexTab + * the index of the tab + * @param scilabClose + * if true, save dialog confirmation cannot be canceled + * @return if the tab has been really closed + */ + public boolean closeTabAt(int indexTab, boolean scilabClose, boolean confirmation) { + ScilabEditorPane textPaneAt = getTextPane(indexTab); + + /* + * Test for modification added after bug 5103 fix: do not ask the user + * for an Untitled not-modified file saving when closing SciNotes + */ + if (confirmation && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) { + if (!save(indexTab, false, scilabClose)) { + return false; + } + } + + textPaneAt.close(); + + if (textPaneAt.getName() == null) { + String closedTabName = tabPane.getScilabTitleAt(indexTab); + String closedTabNameIndex = closedTabName.substring(closedTabName.length() - 1, closedTabName.length()); + tabList.remove(Integer.valueOf(closedTabNameIndex)); + closedTabList.add(Integer.valueOf(closedTabNameIndex)); + } + + // correction for bug 5404, closing the last tabPane generate an + // exception + // that's why we need to remove ChangeListeners before closing + if ((indexTab == 0) && (getTabPane().getTabCount() == 1)) { + for (int i = 0; i < tabPane.getChangeListeners().length; i++) { + tabPane.removeChangeListener(tabPane.getChangeListeners()[i]); + } + } + + // Remove the filename associated with the tab from the list of open + // files. + if (!protectOpenFileList) { + ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt); + } + + if (navigator != null) { + navigator.removePane(textPaneAt); + } + + tabPane.remove(indexTab); + + textPaneAt = getTextPane(); + if (textPaneAt != null) { + if (navigator != null) { + navigator.update((ScilabDocument) textPaneAt.getDocument()); + } + } + return true; + } + + public boolean checkToCloseTabAt(int index) { + ScilabEditorPane textPaneAt = getTextPane(index); + + /* + * Test for modification added after bug 5103 fix: do not ask the user + * for an Untitled not-modified file saving when closing SciNotes + */ + if (textPaneAt != null && ((ScilabDocument) textPaneAt.getDocument()).isContentModified()) { + if (!save(index, false, false)) { + return false; + } + } + + return true; + } + + /** + * Set or unset protection of the currently open file list. Call before + * closing tabs if the tabs should be restored when scinotes restarts. + * + * @param protect + * Enables protection of the open file list if true. + */ + public void setProtectOpenFileList(boolean protect) { + protectOpenFileList = protect; + } + + /** + * Determines if this editor is the only editor instance. + * + * @return true if this is the last editor instance. + */ + public boolean isOnlyInstance() { + if (scinotesList.size() > 1) { + return false; + } + + return true; + } + + /** + * @return the list of the different openened editors + */ + public static List<SciNotes> getSciNotesList() { + return scinotesList; + } + + /** + * Save a file. + * + * @param indexTab + * the textPane index containing the file contents + * @return execution status + */ + public boolean save(int indexTab) { + return save(indexTab, false, false); + } + + /** + * Save a file. + * + * @param indexTab + * the textPane index containing the file contents + * @param force + * : force save without confirmation dialog ( SaveAction ) + * @return execution status + */ + public boolean save(int indexTab, boolean force) { + return save(indexTab, force, false); + } + + /** + * Save a file. + * + * @param indexTab + * the textPane index containing the file contents + * @param force + * : force save without confirmation dialog ( SaveAction ) + * @param scilabClose + * : if true, save dialog confirmation cannot be canceled + * @return execution status + */ + public boolean save(int indexTab, boolean force, boolean scilabClose) { + ScilabEditorPane textPaneAt = getTextPane(indexTab); + getTabPane().setSelectedIndex(indexTab); + + // if the file ( empty, new or loaded ) is not modified, exit save + // process and return true + if (!textPaneAt.checkExternalModif() && !((ScilabDocument) textPaneAt.getDocument()).isContentModified() && (textPaneAt.getName() != null)) { + /* + * Bug + * 5103 + * fix + */ + return true; + } + + if (!force) { + AnswerOption answer; + if (scilabClose) { + answer = ScilabModalDialog.show(this, String.format(SciNotesMessages.MODIFIED, textPaneAt.getShortName()), SciNotesMessages.SCILAB_EDITOR, + IconType.QUESTION_ICON, ButtonType.YES_NO); + } else { + answer = ScilabModalDialog.show(this, String.format(SciNotesMessages.MODIFIED, textPaneAt.getShortName()), SciNotesMessages.SCILAB_EDITOR, + IconType.QUESTION_ICON, ButtonType.YES_NO_CANCEL); + } + + switch (answer) { + case YES_OPTION: // Yes, continue + break; + case NO_OPTION:// No, exit and returns true + return true; + case CANCEL_OPTION: // Cancel, exit and return false + return false; + default: + break; + } + } + + String fileToSave = textPaneAt.getName(); + if (fileToSave == null) { + // need a filename, call chooseFileToSave + fileToSave = chooseFileToSave(SciNotesMessages.SAVE); + } else { + // check if the file has been modified by external software + fileToSave = checkExternalModification(fileToSave); + } + + if (fileToSave == null || fileToSave.length() == 0) { + return true; /* + * Bug 5189: The user cancels ==> do not want an error + * message + */ + } + + File newSavedFile = new File(fileToSave); + + if (!SaveFile.doSave(textPaneAt, indexTab, newSavedFile, editorKit)) { + return false; + } + + ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument(); + styledDocument.setContentModified(false); + + textPaneAt.setLastModified(newSavedFile.lastModified()); + + if (textPaneAt.getName() == null) { + String name = getTabPane().getScilabTitleAt(indexTab); + String index = name.substring(name.length() - 1, name.length()); + tabList.remove(Integer.valueOf(index)); + closedTabList.add(Integer.valueOf(index)); + } + + textPaneAt.setName(fileToSave); + getTabPane().setTitleAt(indexTab, newSavedFile.getName()); + + setTitle(textPaneAt.getTitle()); + ConfigSciNotesManager.saveToOpenFiles(fileToSave, this, textPaneAt); + + return true; + } + + /** + * Overwrite the file at a given index. + * + * @param indexTab + * the textPane index containing the file contents + * @return execution status + */ + public boolean overwrite(int indexTab) { + ScilabEditorPane textPaneAt = getTextPane(indexTab); + String fileToSave = textPaneAt.getName(); + if (fileToSave == null) { + return true; + } + + File newSavedFile = new File(fileToSave); + if (!newSavedFile.exists()) { + return true; + } + + if (!SaveFile.doSave(textPaneAt, indexTab, newSavedFile, editorKit)) { + return false; + } + + ScilabDocument styledDocument = (ScilabDocument) textPaneAt.getDocument(); + styledDocument.setContentModified(false); + + getTabPane().setTitleAt(getTabPane().getSelectedIndex(), newSavedFile.getName()); + + // Get current file path for Execute file into Scilab + getTextPane().setLastModified(newSavedFile.lastModified()); + + textPaneAt.setName(fileToSave); + setTitle(textPaneAt.getTitle()); + + return true; + } + + /** + * Check for external modification. If it is the case, propose to select a + * new file name. + * + * @param filename + * The name of the file + * @return the filename where to save + */ + public String checkExternalModification(String filename) { + File newSavedFile = new File(filename); + if (newSavedFile.lastModified() > getTextPane().getLastModified()) { + if (ScilabModalDialog.show(this, String.format(SciNotesMessages.EXTERNAL_MODIFICATION, newSavedFile.getPath()), + SciNotesMessages.REPLACE_FILE_TITLE, IconType.QUESTION_ICON, ButtonType.YES_NO) == AnswerOption.NO_OPTION) { + return chooseFileToSave(SciNotesMessages.SAVE); + } + } + return filename; + } + + /** + * Return through a file selector the name of the selected file. + * + * @param title + * the title for JFileChooser + * @return the file picked up by the user + */ + public String chooseFileToSave(String title) { + return chooseFileToSave(title, null); + } + + /** + * Return through a file selector the name of the selected file. + * + * @param title + * the title for JFileChooser + * @param path + * the path where to open the filechooser + * @return the file picked up by the user + */ + public String chooseFileToSave(String title, String path) { + String extension = new String(); + + String initialDirectoryPath = path; + if (initialDirectoryPath == null) { + initialDirectoryPath = getTextPane().getName(); + } + if (initialDirectoryPath == null) { + if (firstOpen) { + initialDirectoryPath = CommonFileUtils.getCWD(); + firstOpen = false; + } else { + initialDirectoryPath = ConfigManager.getLastOpenedDirectory(); + } + } + + SciFileFilter sceFilter = new SciFileFilter(ALL_SCE_FILES, null, 0); + SciFileFilter sciFilter = new SciFileFilter(ALL_SCI_FILES, null, 1); + SciFileFilter scxFilter = new SciFileFilter(ALL_SCX_FILES, null, 2); + SciFileFilter tstFilter = new SciFileFilter(ALL_TST_FILES, null, 3); + SciFileFilter startFilter = new SciFileFilter(ALL_START_FILES, null, 4); + SciFileFilter quitFilter = new SciFileFilter(ALL_QUIT_FILES, null, 5); + SciFileFilter demFilter = new SciFileFilter(ALL_DEM_FILES, null, 6); + SciFileFilter allFilter = new SciFileFilter(ALL_FILES, null, 7); + SciFileFilter allScilabFilter = new SciFileFilter(ALL_SCILAB, null, 8); + + SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser()); + + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.setInitialDirectory(initialDirectoryPath); + fileChooser.setUiDialogType(Juigetfile.SAVE_DIALOG); + + // order is also important here + fileChooser.addChoosableFileFilter(sceFilter); + fileChooser.addChoosableFileFilter(sciFilter); + fileChooser.addChoosableFileFilter(scxFilter); + fileChooser.addChoosableFileFilter(tstFilter); + fileChooser.addChoosableFileFilter(startFilter); + fileChooser.addChoosableFileFilter(quitFilter); + fileChooser.addChoosableFileFilter(demFilter); + fileChooser.addChoosableFileFilter(allFilter); + fileChooser.addChoosableFileFilter(allScilabFilter); + + // select default file type + fileChooser.setFileFilter(sceFilter); + fileChooser.setTitle(title); + + String name = getTextPane().getName(); + if (name == null) { + name = ((ScilabDocument) getTextPane().getDocument()).getFirstFunctionName(); + if (name != null) { + name += SCI_EXTENSION; + } + } + + if (name != null) { + fileChooser.setSelectedFile(new File(name)); + } + + int retval = fileChooser.showSaveDialog(this); + + if (retval == JFileChooser.APPROVE_OPTION) { + File f = fileToCanonicalFile(fileChooser.getSelectedFile()); + initialDirectoryPath = f.getPath(); + if (f.exists()) { + if (ScilabModalDialog.show(this, SciNotesMessages.REPLACE_FILE_TITLE, SciNotesMessages.FILE_ALREADY_EXIST, IconType.QUESTION_ICON, + ButtonType.YES_NO) == AnswerOption.NO_OPTION) { + return chooseFileToSave(SciNotesMessages.SAVE); + } + } + + /* we test if the file has already a scilab extension */ + boolean hasNoExtension = true; + + // if the file name is like this : any character , a dot , then + // 2,3or 4 characters, then + // we consider the file has already an extension + // we previously only check for .sci and .sce extension, but what if + // the user open a txt file + String fileName = f.getName(); + if (fileName.lastIndexOf(DOT) != -1) { + if (fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() >= 2 + && fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length() <= 4) { + hasNoExtension = false; + } + } + + /* if no extension , we add it */ + if (hasNoExtension) { + if (fileChooser.getFileFilter() == sciFilter) { + extension = SCI_EXTENSION; + } else if (fileChooser.getFileFilter() == sceFilter) { + extension = SCE_EXTENSION; + } else if (fileChooser.getFileFilter() == scxFilter) { + extension = SCE_EXTENSION; + } else if (fileChooser.getFileFilter() == tstFilter) { + extension = TST_EXTENSION; + } else if (fileChooser.getFileFilter() == startFilter) { + extension = START_EXTENSION; + } else if (fileChooser.getFileFilter() == quitFilter) { + extension = QUIT_EXTENSION; + } else if (fileChooser.getFileFilter() == demFilter) { + extension = DEM_EXTENSION; + } else { + extension = ""; + } + return f.getPath() + extension; + } + + if (initialDirectoryPath != null) { + ConfigManager.saveLastOpenedDirectory(initialDirectoryPath); + } + + return f.getPath(); + } else if (retval == JFileChooser.CANCEL_OPTION) { + return ""; + } + + return null; + } + + /** + * Save a file. + * + * @param path + * the initial path where the filechooser will be open + * @return execution status + */ + public boolean saveAs(String path) { + String filename = chooseFileToSave(SciNotesMessages.SAVE_AS, path); + if (filename == null || filename.length() == 0) { + return true; + } + + File f = new File(filename); + ScilabDocument styledDocument = (ScilabDocument) getTextPane().getDocument(); + + if (!SaveFile.doSave(getTextPane(), getTabPane().getSelectedIndex(), f, editorKit)) { + return false; + } + + if (getTextPane().getName() == null) { + String name = getTabPane().getScilabTitleAt(getTabPane().getSelectedIndex()); + String index = name.substring(name.length() - 1, name.length()); + tabList.remove(Integer.valueOf(index)); + closedTabList.add(Integer.valueOf(index)); + } + + firstOpen = false; + ConfigManager.saveLastOpenedDirectory(f.getPath()); + ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath()); + ConfigSciNotesManager.renameOpenFilesItem(f.getPath(), this, getTextPane()); + getTextPane().setName(f.getPath()); + getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName()); + setTitle(getTextPane().getTitle()); + + RecentFileAction.updateRecentOpenedFilesMenu(this); + + if (navigator != null) { + navigator.update(styledDocument); + } + + styledDocument.setContentModified(false); + getTextPane().setLastModified(f.lastModified()); + getTextPane().setReadOnly(false); + getInfoBar().setText(getTextPane().getInfoBarText()); + + return true; + } + + /** + * Create a new tab in SciNotes. + * + * @param title + * the title of the tab + * @return the text component inside the tab + */ + public ScilabEditorPane addTab(String title) { + return addTab(title, Integer.MAX_VALUE); + } + + /** + * Create a new tab in SciNotes. + * + * @param title + * the title of the tab + * @param index + * the index where to put the new tab + * @return the text component inside the tab + */ + public ScilabEditorPane addTab(String title, int index) { + return addTab(title, index, 0); + } + + /** + * Create a new tab in SciNotes. + * + * @param title + * the title of the tab + * @param index + * the index where to put the new tab + * @return the text component inside the tab + */ + public ScilabEditorPane addTab(String title, int index, int caretPos) { + ScilabEditorPane sep = new ScilabEditorPane(this); + initPane(sep); + int ind = Math.min(Math.max(0, index), tabPane.getTabCount()); + tabPane.insertTab(title, null, sep.getEditorComponent(), "", ind); + tabPane.setSelectedIndex(ind); + initInputMap(sep); + updateTabTitle(); + getInfoBar().setText(sep.getInfoBarText()); + repaint(); + sep.init(caretPos); + return sep; + } + + public void addRestoreTab() { + try { + JPanel panel = RestoreOpenedFilesAction.getTab(this, getUUID().toString()); + if (panel != null) { + tabPane.addTab("Restore", panel); + } + } catch (Exception e) { + System.err.println(e); + } + } + + /** + * Init a pane + * + * @param pane + * the pane to init + */ + public void initPane(ScilabEditorPane pane) { + initPane(pane, !SciNotesOptions.getSciNotesDisplay().wrapLines); + } + + /** + * Init the EditorPane. + * + * @param pane + * the EditorPane + * @param plain + * true for a plain view or false for a wrapped view + */ + public void initPane(ScilabEditorPane pane, boolean plain) { + setHighlight(pane); + ScilabEditorKit kit = new ScilabEditorKit(plain); + pane.setEditorKit(kit); + + // Panel of line number for the text pane + pane.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami); + activateHelpOnTyping(pane); + + pane.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + pane.setFont(kit.getStylePreferences().tokenFonts[0]); + + pane.setBackground(SciNotesOptions.getSciNotesDisplay().backgroundColor); + pane.setCaretColor(SciNotesOptions.getSciNotesDisplay().caretColor); + + pane.setFocusable(true); + pane.setRequestFocusEnabled(true); + pane.setDragEnabled(true); /* Bug 5497 */ + + DropFilesListener dndTarget = new DropFilesListener(pane); + + pane.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(this)); + } + + /** + * Init the EditorPane with the InputMap found in ConfigSciNotesManager + * + * @param pane + * the EditorPane + */ + public void initInputMap(ScilabEditorPane pane) { + setKeyStrokeAction(pane, this); + LineBeautifierAction.putInInputMap(pane); + InsertOverwriteAction.putInInputMap(pane); + } + + /** + * Split the EditorPane + * + * @param vertical + * true for a vertical split + */ + public void splitTab(boolean vertical) { + ScilabEditorPane pane = getTextPane(); + Component bottom = pane.getEditorComponent().getBottom(); + int state = pane.getXln().getState(); + ScilabEditorPane leftPane = new ScilabEditorPane(editor); + ScilabEditorPane rightPane = new ScilabEditorPane(editor); + if (navigator != null) { + navigator.changePaneOnSplit(pane, leftPane); + } + initPane(leftPane, true); + initPane(rightPane, true); + leftPane.setOtherPaneInSplit(rightPane); + rightPane.setOtherPaneInSplit(leftPane); + pane.copyProps(leftPane); + pane.copyProps(rightPane); + ScilabDocument doc = (ScilabDocument) pane.getDocument(); + leftPane.setDocument(doc); + rightPane.setDocument(doc); + leftPane.setCaretPosition(0); + rightPane.setCaretPosition(0); + JSplitPane split; + if (vertical) { + split = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + } else { + split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); + } + leftPane.getXln().setWhereamiLineNumbering(state); + rightPane.getXln().setWhereamiLineNumbering(state); + split.setLeftComponent(leftPane.getScrollPane()); + split.setRightComponent(rightPane.getScrollPane()); + split.setResizeWeight(0.5); + rightPane.setEditorComponent(leftPane.getEditorComponent()); + leftPane.setSplitPane(split); + rightPane.setSplitPane(split); + + activateHelpOnTyping(leftPane); + activateHelpOnTyping(rightPane); + initInputMap(leftPane); + initInputMap(rightPane); + if (doc.getBinary()) { + leftPane.setBinary(true); + rightPane.setBinary(true); + } + getInfoBar().setText(leftPane.getInfoBarText()); + updateTabTitle(); + tabPane.setComponentAt(tabPane.getSelectedIndex(), leftPane.getEditorComponent()); + leftPane.getEditorComponent().insertBottomComponent(bottom); + leftPane.requestFocus(); + } + + /** + * Remove a split + */ + public void removeSplit() { + if (((EditorComponent) tabPane.getSelectedComponent()).isSplited()) { + ScilabEditorPane pane = new ScilabEditorPane(editor); + ScilabEditorPane textpane = getTextPane(); + Component bottom = textpane.getEditorComponent().getBottom(); + if (navigator != null) { + navigator.changePaneOnSplit(textpane, pane); + } + initPane(pane); + textpane.setOtherPaneInSplit(null); + textpane.copyProps(pane); + ScilabDocument doc = (ScilabDocument) textpane.getDocument(); + pane.setDocument(doc); + pane.setCaretPosition(0); + activateHelpOnTyping(pane); + tabPane.setComponentAt(tabPane.getSelectedIndex(), pane.getEditorComponent()); + initInputMap(pane); + if (doc.getBinary()) { + pane.setBinary(true); + } + getInfoBar().setText(pane.getInfoBarText()); + updateTabTitle(); + pane.getEditorComponent().insertBottomComponent(bottom); + pane.requestFocus(); + } + } + + /** + * Create an empty tab inside SciNotes. + * + * @return the text component inside the tab + */ + public ScilabEditorPane addEmptyTab() { + ScilabEditorPane sep; + int n = getNumberForEmptyTab(); + sep = addTab(SciNotesMessages.UNTITLED + n); + sep.setShortName(SciNotesMessages.UNTITLED + n); + sep.setTitle(SciNotesMessages.UNTITLED + n); + setTitle(sep.getTitle()); + SciNotesOptions.Header header = SciNotesOptions.getSciNotesHeader(); + if (header.header != null) { + ((ScilabDocument) sep.getDocument()).disableUndoManager(); + try { + sep.getDocument().insertString(0, header.header, null); + } catch (BadLocationException e) { } + sep.init(header.header.length()); + ((ScilabDocument) sep.getDocument()).setContentModified(false); + ((ScilabDocument) sep.getDocument()).enableUndoManager(); + } + + return sep; + } + + /** + * Get an integer used for untitled document + */ + public int getNumberForEmptyTab() { + if (closedTabList.size() > 0) { + Integer n = Collections.min(closedTabList); + closedTabList.remove(n); + return n.intValue(); + } else { + numberOfUntitled++; + tabList.add(Integer.valueOf(numberOfUntitled)); + return numberOfUntitled; + } + } + + /** + * Add or remove '*' prefix in current tab tile according to + * isContentModified(). + */ + public void updateTabTitle() { + updateTabTitle(getTabPane().getSelectedIndex()); + } + + /** + * Add or remove '*' prefix in tab title (corresponding to the given index) according to + * isContentModified(). + */ + public void updateTabTitle(int index) { + StringBuffer newTitle = new StringBuffer(); + ScilabEditorPane currentTextPane = getTextPane(index); + if (((ScilabDocument) currentTextPane.getDocument()).isContentModified()) { + newTitle.append('*'); + } + + String textPaneName = currentTextPane.getName(); + try { + File f = new File(textPaneName); + newTitle.append(f.getName()); + } catch (NullPointerException e) { // not a file name, no path prefix to + // remove, but maybe a '*' + textPaneName = getTabPane().getScilabTitleAt(index); + if (textPaneName.charAt(0) == '*') { + newTitle.append(textPaneName.substring(1, textPaneName.length())); + } else { + newTitle.append(textPaneName); + } + } + getTabPane().setTitleAt(index, newTitle.toString()); + } + + /** + * @param button + * the UndoButton used in this editor + */ + public void setUndoButton(JButton button) { + undoButton = button; + enableUndoButton(false); + } + + /** + * @param b + * true to enable the button + */ + public void enableUndoButton(boolean b) { + if (undoButton != null) { + undoButton.setEnabled(b); + } + } + + /** + * Undo last modification. + */ + public void undo() { + ScilabDocument doc = (ScilabDocument) getTextPane().getDocument(); + synchronized (doc) { + doc.getUndoManager().undo(); + } + } + + /** + * @param button + * the RedoButton used in this editor + */ + public void setRedoButton(JButton button) { + redoButton = button; + enableRedoButton(false); + } + + /** + * @param b + * true to enable the button + */ + public void enableRedoButton(boolean b) { + if (redoButton != null) { + redoButton.setEnabled(b); + } + } + + /** + * Redo last modification. + */ + public void redo() { + ScilabDocument doc = (ScilabDocument) getTextPane().getDocument(); + synchronized (doc) { + doc.getUndoManager().redo(); + } + } + + /** + * Reload a file inside SciNotes. + * + * @param index + * the index + */ + public void reload(int index) { + ScilabEditorPane textPaneAt = getTextPane(index); + if (textPaneAt != null && textPaneAt.getName() != null) { + if ((index == 0) && (getTabPane().getTabCount() == 1)) { + for (int j = 0; j < tabPane.getChangeListeners().length; j++) { + tabPane.removeChangeListener(tabPane.getChangeListeners()[j]); + } + } + ConfigSciNotesManager.removeFromOpenFiles(this, textPaneAt); + tabPane.remove(index); + File f = new File(textPaneAt.getName()); + if (f.exists()) { + loadFile(f, index); + } else { + createNewFile(f); + } + } + } + + /** + * Load a file inside SciNotes. + * + * @param f + * the file to open + */ + public void readFile(File f) { + /** Is this file already opened */ + boolean alreadyOpened = false; + for (int i = 0; i < tabPane.getTabCount(); i++) { + ScilabEditorPane textPaneAt = getTextPane(i); + if (f.getAbsolutePath().equals(textPaneAt.getName())) { + /* File is already opnened */ + tabPane.setSelectedIndex(i); + alreadyOpened = true; + break; + } + } + + if (!alreadyOpened) { + if (f.exists()) { + loadFile(f); + } else { + createNewFile(f); + } + } + } + + /** + * Load a file inside SciNotes. + * + * @param file + * the file to open + */ + public void readFileAndWait(File file) { + /** Is this file already opened */ + File f = file; + boolean alreadyOpened = false; + int index = -1; + for (int i = 0; i < tabPane.getTabCount(); i++) { + ScilabEditorPane textPaneAt = getTextPane(i); + if (textPaneAt != null && f.getAbsolutePath().equals(textPaneAt.getName())) { + /* File is already opened */ + tabPane.setSelectedIndex(i); + if (f.lastModified() > textPaneAt.getLastModified()) { + + /* + * Create a new messagebox to know what the user wants to do + * if the file has been modified outside SciNotes + */ + MessageBox messageBox = ScilabMessageBox.createMessageBox(); + messageBox.setTitle(SciNotesMessages.REPLACE_FILE_TITLE); + messageBox.setMessage(String.format(SciNotesMessages.EXTERNAL_MODIFICATION, textPaneAt.getName())); + + String[] labels = new String[] { SciNotesMessages.RELOAD, SciNotesMessages.OVERWRITE, SciNotesMessages.IGNORE }; + messageBox.setButtonsLabels(labels); + + messageBox.setIcon("question"); // Question icon + + messageBox.setParentForLocation(this); // Centered on + // SciNotes main + // window + + messageBox.displayAndWait(); // Waits for a user action + + switch (messageBox.getSelectedButton()) { + case 1: // Reload + if ((i == 0) && (getTabPane().getTabCount() == 1)) { + for (int j = 0; j < tabPane.getChangeListeners().length; j++) { + tabPane.removeChangeListener(tabPane.getChangeListeners()[j]); + } + } + tabPane.remove(i); + f = new File(textPaneAt.getName()); + index = i; + break; + case 2: // Overwrite 2 + overwrite(i); + alreadyOpened = true; + break; + default: // Ignore + alreadyOpened = true; + } + } else { + alreadyOpened = true; + } + break; + } + } + + if (!alreadyOpened) { + if (f.exists()) { + loadFile(f, index); + } else { + createNewFile(f); + } + } + } + + public int getTextPaneIndex(ScilabEditorPane sep) { + int n = tabPane.getTabCount(); + for (int i = 0; i < n; ++i) { + ScilabEditorPane pane = getTextPane(i); + if (pane != null && (pane == sep || pane.getOtherPaneInSplit() == sep)) { + return i; + } + } + + return -1; + } + + /** + * Get current text component. If the window is splitted, then return the + * focused text component. + * + * @return the text component + */ + public ScilabEditorPane getTextPane() { + try { + if (tabPane.getSelectedComponent() instanceof EditorComponent) { + EditorComponent c = (EditorComponent) tabPane.getSelectedComponent(); + ScilabEditorPane pane = c.getEditorPane(); + if (ScilabEditorPane.getFocusedPane() == pane.getOtherPaneInSplit()) { + return pane.getOtherPaneInSplit(); + } + + return pane; + } + } catch (NullPointerException e) { + } catch (ArrayIndexOutOfBoundsException e) { + } + + return null; + } + + /** + * Get text component at index. + * + * @param index + * the index of the textpane + * @return the text component + */ + public ScilabEditorPane getTextPane(int index) { + try { + if (tabPane.getComponentAt(index) instanceof EditorComponent) { + EditorComponent c = (EditorComponent) tabPane.getComponentAt(index); + ScilabEditorPane pane = c.getEditorPane(); + if (ScilabEditorPane.getFocusedPane() == pane.getOtherPaneInSplit()) { + return pane.getOtherPaneInSplit(); + } + + return pane; + } + } catch (NullPointerException e) { + } catch (ArrayIndexOutOfBoundsException e) { + } + + return null; + } + + /** + * Set the keystroke actions + */ + public static void setAllMenus() { + for (SciNotes ed : scinotesList) { + SciNotesGUI.reinitMenus(ed); + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(ed)); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().setComponentPopupMenu(SciNotesGUI.generateRightClickPopup(ed)); + } + } + } + } + + /** + * Set the keystroke actions + */ + public static void setKeyStrokeActions() { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + ed.initInputMap(sep); + if (sep.getOtherPaneInSplit() != null) { + ed.initInputMap(sep.getOtherPaneInSplit()); + } + } + } + } + + /** + * Enable the whereami-line numbering + * + * @param state + * int + */ + public static void setWhereamiLineNumbering() { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami); + } + } + ed.repaint(); + } + } + + /** + * Auto-indent mode management + * + * @param b + * true to activate auto-indent mode + */ + public static void setAutoIndent() { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + ((ScilabDocument) sep.getDocument()).setAutoIndent(SciNotesOptions.getSciNotesDisplay().automaticIndent); + if (sep.getOtherPaneInSplit() != null) { + ((ScilabDocument) sep.getOtherPaneInSplit().getDocument()).setAutoIndent(SciNotesOptions.getSciNotesDisplay().automaticIndent); + } + } + } + } + + /** + * Horizontal Wrap mode management + * + * @param b + * true to activate horizontal wrapping mode + */ + public static void setHorizontalWrap() { + if (SciNotesOptions.getSciNotesDisplay().wrapLines != mustWrapLines) { + mustWrapLines = SciNotesOptions.getSciNotesDisplay().wrapLines; + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + if (sep.getOtherPaneInSplit() == null) { + ScilabEditorPane pane = new ScilabEditorPane(editor); + ed.initPane(pane, !mustWrapLines); + sep.copyProps(pane); + pane.setDocument(sep.getDocument()); + pane.setCaretPosition(sep.getCaretPosition()); + pane.getXln().setWhereamiLineNumbering(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami); + ed.tabPane.setComponentAt(i, pane.getEditorComponent()); + SciNotes.activateHelpOnTyping(pane); + ed.initInputMap(pane); + if (((ScilabDocument) sep.getDocument()).getBinary()) { + pane.setBinary(true); + } + ed.getInfoBar().setText(pane.getInfoBarText()); + } + } + } + } + } + + /** + * Set a line numbering compatible with the whereami function + * @param state 0 for nothing, 1 for normal and 2 for whereami + */ + + /** + * Enable the highlighted line in this editor + * + * @param b + * boolean + */ + public static void enableHighlightedLine(boolean b) { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine); + } + } + } + } + + /** + * Enable the help on typing in the current textPane + * + * @param pane + * the pane + */ + public static void activateHelpOnTyping(ScilabEditorPane pane) { + pane.activateHelpOnTyping(); + } + + /** + * Enable the help on typing in this editor + */ + public static void activateHelpOnTyping() { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.activateHelpOnTyping(); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().activateHelpOnTyping(); + } + } + } + } + + /** + * Set the color of the highlighted line in this editor + * + * @param c + * Color + */ + public static void setDefaultTabulation() { + TabManager.Tabulation tab = new TabManager.Tabulation(); + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.getTabManager().setTabulation(tab); + View view = ((ScilabDocument) sep.getDocument()).getView(); + if (view != null) { + if (view instanceof ScilabView) { + ((ScilabView) view).setTabRepresentation(tab); + ((ScilabView) view).reinitialize(); + } else { + ((ScilabPlainView) view).setTabRepresentation(tab); + ((ScilabPlainView) view).reinitialize(); + } + } + } + } + } + + /** + * Set the color of the highlighted line in this editor + * + * @param c + * Color + */ + public static void updatePanes(SciNotesConfiguration.Conf conf) { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.configurationChanged(conf); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().configurationChanged(conf); + } + sep.repaint(); + } + } + } + + public static void updateFontSize(int inc) { + Font baseFont = null; + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + ((ScilabEditorKit) sep.getEditorKit()).getStylePreferences().changeBaseFontSize(inc); + if (baseFont == null) { + baseFont = ((ScilabEditorKit) sep.getEditorKit()).getStylePreferences().getBaseFont(); + } + if (sep.getOtherPaneInSplit() != null) { + ((ScilabEditorKit) sep.getOtherPaneInSplit().getEditorKit()).getStylePreferences().changeBaseFontSize(n); + sep.getOtherPaneInSplit().resetFont(); + } + sep.resetFont(); + } + } + + if (baseFont != null) { + ScilabContext.saveFont(baseFont); + } + } + + /** + * Set the color of the highlighted line in this editor + * + * @param c + * Color + */ + public static void setHighlightedLineColor() { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor); + } + } + } + } + + /** + * Set the color of the contour of the highlighted line in this editor + * + * @param c + * Color + */ + public static void setHighlightedContourColor() { + for (SciNotes ed : scinotesList) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + sep.setHighlightedContourColor(null); + if (sep.getOtherPaneInSplit() != null) { + sep.getOtherPaneInSplit().setHighlightedContourColor(null); + } + } + } + } + + /** + * Set the highlighted line in this textPane + * + * @param sep + * ScilabEditorPane + */ + public static void setHighlight(ScilabEditorPane sep) { + sep.enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine); + sep.setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor); + sep.setHighlightedContourColor(null); + } + + /** + * Get SciNotes as a Tab. + * + * @return SciNotes instance + * @see org.scilab.modules.gui.tab.Tab#getAsSimpleTab() + */ + public SimpleTab getAsSimpleTab() { + return this; + } + + /** + * Get SciNotes parent Window. + * + * @return parent Window + * @see org.scilab.modules.gui.tab.Tab#getParentWindow() + */ + public SwingScilabWindow getParentWindow() { + if (parentWindow == null) { + return super.getParentWindow(); + } + return parentWindow; + } + + /** + * Get the UUID associated with the editor instance. + * + * @return unique identifier + */ + public UUID getUUID() { + return uuid; + } + + /** + * Add a status bar to SciNotes. + * + * @param infoBarToAdd + * the status bar to be added + * @see org.scilab.modules.gui.uielement.UIElement#addInfoBar(org.scilab.modules.gui.textbox.TextBox) + */ + public void addInfoBar(TextBox infoBarToAdd) { + setInfoBar(infoBarToAdd); + } + + /** + * Add a menu bar to SciNotes. + * + * @param menuBarToAdd + * the menu bar to be added + * @see org.scilab.modules.gui.uielement.UIElement#addMenuBar(org.scilab.modules.gui.menubar.MenuBar) + */ + public void addMenuBar(MenuBar menuBarToAdd) { + setMenuBar(menuBarToAdd); + } + + /** + * Add a tool bar to SciNotes. + * + * @param toolBarToAdd + * the tool bar to be added + * @see org.scilab.modules.gui.uielement.UIElement#addToolBar(org.scilab.modules.gui.toolbar.ToolBar) + */ + public void addToolBar(ToolBar toolBarToAdd) { + setToolBar(toolBarToAdd); + } + + /** + * Get SciNotes main ScilabTabbedPane. + * + * @return SciNotes main ScilabTabbedPane + */ + public ScilabTabbedPane getTabPane() { + return tabPane; + } + + /** + * Set SciNotes main ScilabTabbedPane. + * + * @param tabPane + * SciNotes main ScilabTabbedPane + */ + public void setTabPane(ScilabTabbedPane tabPane) { + this.tabPane = tabPane; + } + + /** + * Load a file and add it at the end + * + * @param f + * the file to load + */ + public void loadFile(File f) { + loadFile(f, -1); + } + + /** + * Load a file and add it at the index + * + * @param f + * the file to load + * @param index + * the index where to put the file + */ + public void loadFile(File f, int index) { + ScilabDocument styleDocument = null; + ScilabEditorPane theTextPane; + + // File exist + if (f.exists()) { + if (!f.canRead()) { + ScilabModalDialog.show(this, SciNotesMessages.NOTREADABLE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + if (getTabPane().getTabCount() == 0) { + addEmptyTab(); + } + return; + } + + getInfoBar().setText(SciNotesMessages.LOADING); + + if (index != -1) { + theTextPane = addTab(f.getName(), index); + } else { + theTextPane = addTab(f.getName()); + } + styleDocument = (ScilabDocument) theTextPane.getDocument(); + styleDocument.disableUndoManager(); + theTextPane.setLastModified(f.lastModified()); + + try { + styleDocument.setUpdater(false); + boolean indentMode = styleDocument.getAutoIndent(); + styleDocument.setAutoIndent(false); + try { + ((ScilabEditorKit) editorKit).read(this, f, styleDocument, 0); + } catch (BadLocationException e) { + e.printStackTrace(); + } + styleDocument.setAutoIndent(indentMode); + styleDocument.setUpdater(true); + } catch (IOException ioex) { + ioex.printStackTrace(); + } + + theTextPane.setName(f.getAbsolutePath()); + getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName()); + setTitle(theTextPane.getTitle()); + styleDocument.setContentModified(false); + styleDocument.enableUndoManager(); + + if (styleDocument.getBinary()) { + theTextPane.setBinary(true); + } + + if (!f.canWrite()) { + getTextPane().setReadOnly(true); + JOptionPane.showMessageDialog(SciNotes.this, SciNotesMessages.READONLY); + } + + getInfoBar().setText(theTextPane.getInfoBarText()); + + EncodingAction.updateEncodingMenu((ScilabDocument) getTextPane().getDocument()); + + firstOpen = false; + ConfigManager.saveLastOpenedDirectory(f.getPath()); + ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath()); + ConfigSciNotesManager.saveToOpenFiles(f.getPath(), this, getTextPane()); + + // Empty the undo Manager + UndoManager undo = ((ScilabDocument) getTextPane().getDocument()).getUndoManager(); + undo.discardAllEdits(); + + if (getTabPane().getTabCount() == 2) { + ScilabEditorPane pane = getTextPane(0); + if (pane != null && pane.getName() == null && !((ScilabDocument) pane.getDocument()).isContentModified()) { + closeTabAt(0); + } + } + } + } + + /** + * Creates a file if it doesn't exist + * + * @param f + * the file to create + */ + public void createNewFile(File f) { + ScilabEditorPane theTextPane = addEmptyTab(); + ScilabDocument styleDocument = null; + int choice = JOptionPane.showConfirmDialog(SciNotes.this, String.format(SciNotesMessages.FILE_DOESNT_EXIST, f.getName()), SCINOTES, + JOptionPane.YES_NO_OPTION); + if (choice == 0) { // OK + styleDocument = (ScilabDocument) theTextPane.getDocument(); + styleDocument.disableUndoManager(); + + BufferedWriter bw = null; + OutputStreamWriter osw = null; + FileOutputStream fos = null; + + try { + fos = new FileOutputStream(f); + osw = new OutputStreamWriter(fos, styleDocument.getEncoding()); + bw = new BufferedWriter(osw); + editorKit.write(bw, styleDocument, 0, styleDocument.getLength()); + bw.flush(); + } catch (IOException e) { + System.err.println(e); + } catch (BadLocationException e) { + System.err.println(e); + } finally { + try { + if (fos != null) { + fos.close(); + } + if (osw != null) { + osw.close(); + } + if (bw != null) { + bw.close(); + } + } catch (IOException e) { + System.err.println(e); + } + } + + firstOpen = false; + ConfigManager.saveLastOpenedDirectory(f.getPath()); + ConfigSciNotesManager.saveToRecentOpenedFiles(f.getPath()); + ConfigSciNotesManager.saveToOpenFiles(theTextPane.getName(), this, theTextPane); + + theTextPane.setName(f.getPath()); + getTabPane().setTitleAt(getTabPane().getSelectedIndex(), f.getName()); + setTitle(theTextPane.getTitle()); + RecentFileAction.updateRecentOpenedFilesMenu(this); + + styleDocument.setContentModified(false); + styleDocument.enableUndoManager(); + theTextPane.setLastModified(f.lastModified()); + } + + getInfoBar().setText(""); + } + + /** + * EditorKit Getter + * + * @return EditorKit + */ + public EditorKit getEditorKit() { + return editorKit; + } + + /** + * @param scinotes + * the focused editor + */ + public static void setEditor(SciNotes scinotes) { + editor = scinotes; + } + + /** + * @return the focused editor + */ + public static SciNotes getEditor() { + return editor; + } + + /** + * EditorKit Setter + * + * @param editorKit + * EditorKit + */ + public void setEditorKit(EditorKit editorKit) { + this.editorKit = editorKit; + } + + /** + * Close scinotes from scilab. + * + * This method can be called outside the EDT thread. + */ + public static void closeSciNotesFromScilab() { + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + SciNotes[] arr = scinotesList.toArray(new SciNotes[0]); + for (int i = 0; i < arr.length; i++) { + arr[i].setProtectOpenFileList(true); + ExitAction.doExit(arr[i]); + } + scinotesList.clear(); + } + }); + } catch (InterruptedException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + } catch (InvocationTargetException e) { + Logger.getLogger(SciNotes.class.getName()).severe(e.toString()); + } + } + + /** + * @param f + * the file + * @return the canonical file if possible + */ + public static File fileToCanonicalFile(File f) { + /* Fix bug 5648 */ + try { + return f.getCanonicalFile(); + } catch (IOException e) { + return f; + } + } + + /** + * Set the shortcuts in the pane relatively to the file + * keysConfiguration.xml + * + * @param sep + * the textpane + * @param ed + * the SciNotes editor + */ + private static void setKeyStrokeAction(ScilabEditorPane sep, SciNotes ed) { + ScilabEditorPane s = ed.getTextPane(0); + if (s != null && s != sep) { + sep.setInputMap(JComponent.WHEN_FOCUSED, s.getInputMap()); + return; + } + + Map<String, KeyStroke> map = getActionKeys(); + ClassLoader loader = ClassLoader.getSystemClassLoader(); + + for (Map.Entry<String, KeyStroke> entry : map.entrySet()) { + String actionName = entry.getKey(); + KeyStroke key = entry.getValue(); + String action = actionToName.get(actionName); + if (key != null) { + if (!action.equals("SciNotesCompletionAction")) { + String className; + if (action.lastIndexOf(DOT) != -1) { + className = action; + } else { + className = DEFAULTACTIONPATH + DOT + action; + } + try { + Class clazz = loader.loadClass(className); + Constructor constructor = clazz.getConstructor(new Class[] { String.class, SciNotes.class }); + Object act = constructor.newInstance(new Object[] { "", ed }); + sep.getInputMap().put(key, act); + } catch (ClassNotFoundException e) { + System.err.println("No action: " + className); + } catch (InstantiationException e) { + System.err.println("Problem to instantiate in action: " + className); + } catch (NoSuchMethodException e) { + System.err.println("No valid constructor in action: " + className); + } catch (IllegalAccessException e) { + System.err.println("The constructor must be public: " + className); + } catch (InvocationTargetException e) { + System.err.println("The constructor in " + className + " threw an exception :"); + e.printStackTrace(); + } + } else { + sep.getInputMap().put(key, new SciNotesCompletionAction(sep, ed)); + } + } + } + + // Add default common shortcuts + sep.getInputMap().put(KeyStroke.getKeyStroke("shift DELETE"), sep.getInputMap().get(map.get("scinotes-cut"))); + sep.getInputMap().put(KeyStroke.getKeyStroke("CUT"), sep.getInputMap().get(map.get("scinotes-cut"))); + sep.getInputMap().put(ScilabKeyStroke.getKeyStroke("OSSCKEY INSERT"), sep.getInputMap().get(map.get("scinotes-copy"))); + sep.getInputMap().put(KeyStroke.getKeyStroke("COPY"), sep.getInputMap().get(map.get("scinotes-copy"))); + sep.getInputMap().put(KeyStroke.getKeyStroke("shift INSERT"), sep.getInputMap().get(map.get("scinotes-paste"))); + sep.getInputMap().put(KeyStroke.getKeyStroke("PASTE"), sep.getInputMap().get(map.get("scinotes-paste"))); + } + + /** + * Execute an action on file + * @param fileName the name of the file + * @param action the action + */ + public static void executeAction(String fileName, ActionOnDocument action) throws IOException { + Charset charset = null; + try { + charset = ScilabEditorKit.tryToGuessEncoding(new File(fileName)); + } catch (CharacterCodingException e) { + throw new IOException(SciNotesMessages.CANNOT_GUESS_ENCODING + ": " + fileName); + } + FileInputStream fis = new FileInputStream(fileName); + InputStreamReader isr = new InputStreamReader(fis, charset); + BufferedReader reader = new BufferedReader(isr); + ScilabDocument doc = new ScilabDocument(); + ScilabEditorKit kit = new ScilabEditorKit(); + try { + kit.read(reader, doc, 0); + } catch (BadLocationException e) { + System.err.println(e); + } + + doc.addDocumentListener(doc); + if (!doc.getBinary()) { + action.actionOn(doc); + } + + reader.close(); + if (doc.isContentModified()) { + SaveFile.doSave(doc, new File(fileName), kit); + } + } + + /** + * Execute an action on file + * @param fileName the name of the file + * @param actionsName the actions as an array + */ + public static boolean executeAction(String fileName, final String[] actionsName) throws IOException { + final boolean[] hasAction = new boolean[] { false }; + ActionOnDocument action = new ActionOnDocument() { + public void actionOn(ScilabDocument doc) throws IOException { + for (String act : actionsName) { + if (act.equalsIgnoreCase("indent")) { + hasAction[0] = true; + org.scilab.modules.scinotes.actions.IndentAction.getActionOnDocument().actionOn(doc); + } else if (act.equalsIgnoreCase("trailing")) { + hasAction[0] = true; + org.scilab.modules.scinotes.actions.RemoveTrailingWhiteAction.getActionOnDocument().actionOn(doc); + } else if (act.equalsIgnoreCase("quote")) { + hasAction[0] = true; + org.scilab.modules.scinotes.actions.DoubleQuoteStringAction.getActionOnDocument().actionOn(doc); + } + } + } + }; + + executeAction(fileName, action); + + return hasAction[0]; + } + + /** + * Execute an action on file + * @param fileName the name of the file + * @param acts actions separated with , or ; + */ + public static void executeAction(String fileName, String acts) throws IOException { + StringTokenizer toks = new StringTokenizer(acts, ",;"); + String[] actions = new String[toks.countTokens()]; + for (int i = 0; i < actions.length; i++) { + actions[i] = toks.nextToken(); + } + executeAction(fileName, actions); + } + + /** + * An interface to implement to execute an action on a document + */ + public static interface ActionOnDocument { + + public void actionOn(ScilabDocument doc) throws IOException; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesAutosave.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesAutosave.java new file mode 100755 index 000000000..94a9b785c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesAutosave.java @@ -0,0 +1,213 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2012 - Scilab Enterprises -Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.swing.Timer; + +import org.scilab.modules.core.Scilab; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.utils.SaveFile; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +public class SciNotesAutosave implements ActionListener { + + private static SciNotesAutosave instance; + private static Set<File> toRemove = new HashSet<File>(); + private boolean isChecking = false; + private Object lock = new Object(); + + static { + Scilab.registerFinalHook(new Runnable() { + public void run() { + for (File f : toRemove) { + if (f.exists()) { + try { + f.delete(); + } catch (Exception e) { } + } + } + } + }); + } + + private Timer timer; + + private SciNotesAutosave() { + timer = new Timer(SciNotesOptions.getSciNotesAutosave().saveEvery * 60 * 1000, this); + timer.setRepeats(true); + timer.start(); + } + + public static void autosave() { + if (SciNotesOptions.getSciNotesAutosave().autoSave) { + startAutosave(); + } else { + stopAutosave(); + } + } + + static void startAutosave() { + if (instance == null && SciNotesOptions.getSciNotesAutosave().autoSave) { + instance = new SciNotesAutosave(); + } + } + + static void stopAutosave() { + if (instance != null) { + instance.timer.stop(); + instance = null; + } + } + + private boolean isChecking() { + synchronized (lock) { + return isChecking; + } + } + + private void isChecking(boolean b) { + synchronized (lock) { + isChecking = b ; + } + } + + private boolean checkSaveDir() { + isChecking(true); + SciNotesOptions.Autosave as = SciNotesOptions.getSciNotesAutosave(); + if (!as.singleDirectory.isEmpty()) { + File dir = new File(as.singleDirectory); + if (!dir.exists()) { + if (AnswerOption.YES_OPTION == ScilabModalDialog.show(null, String.format(SciNotesMessages.NO_EXISTING_DIR, as.singleDirectory), SciNotesMessages.AUTOSAVE, IconType.QUESTION_ICON, ButtonType.YES_NO_CANCEL)) { + if (dir.mkdir()) { + isChecking(false); + + return true; + } + ScilabModalDialog.show(null, String.format(SciNotesMessages.UNABLE_TO_CREATE_DIR, as.singleDirectory), SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + + isChecking(false); + + return false; + } + + if (!dir.isDirectory()) { + ScilabModalDialog.show(null, String.format(SciNotesMessages.NOT_A_DIR, as.singleDirectory), SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + isChecking(false); + + return false; + } + + // we check if a file can be created in this directory + try { + File.createTempFile("autosave_test", null, dir).delete(); + } catch (Exception e) { + System.err.println(e); + ScilabModalDialog.show(null, String.format(SciNotesMessages.NOT_WRITABLE_DIR, as.singleDirectory), SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + isChecking(false); + + return false; + } + } + + isChecking(false); + + return true; + } + + public static File getBackupFile(String name) { + SciNotesOptions.Autosave as = SciNotesOptions.getSciNotesAutosave(); + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); + if (as.appendFilename) { + name += as.appendWith.replaceAll("%date", dateFormat.format(new Date())); + } else { + int dotpos = name.lastIndexOf('.'); + if (dotpos != -1) { + name = name.substring(0, dotpos + 1) + as.replaceWith; + } + } + + File file = new File(name); + String filename = file.getName(); + if (!as.sourceFlag) { + file = new File(as.singleDirectory, filename); + } + + boolean identic = new File(name).equals(file); + + if (identic) { + return null; + } + + return file; + } + + public void actionPerformed(ActionEvent e) { + SciNotesOptions.Autosave as = SciNotesOptions.getSciNotesAutosave(); + if (!isChecking() && as.autoSave && checkSaveDir()) { + boolean saved = false; + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); + for (SciNotes ed : SciNotes.getSciNotesList()) { + int n = ed.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane sep = ed.getTextPane(i); + if (sep != null && sep.getName() != null && !sep.getName().isEmpty() && !sep.checkExternalModif() && ((ScilabDocument) sep.getDocument()).isContentModified() && ((ScilabDocument) sep.getDocument()).isContentModifiedSinceBackup()) { + String name = sep.getName(); + File file = getBackupFile(name); + boolean identic = false; + if (file == null) { + identic = true; + file = new File(name); + } + + boolean success = SaveFile.doSave(sep, i, file, ed.getEditorKit(), false, true, false); + String filename = file.getName(); + if (!saved) { + saved = true; + } + if (!success) { + ed.getInfoBar().setText(String.format(SciNotesMessages.AUTOSAVE_ERROR, filename)); + return; + } else { + ((ScilabDocument) sep.getDocument()).setContentModifiedSinceBackup(false); + if (identic) { + ((ScilabDocument) sep.getDocument()).setContentModified(false); + sep.setLastModified(file.lastModified()); + } else { + if (as.automaticDelete) { + toRemove.add(file); + } + } + } + } + } + if (saved) { + ed.getInfoBar().setText(SciNotesMessages.AUTOSAVE_FINISHED); + } + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesCaret.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesCaret.java new file mode 100755 index 000000000..10f550b2c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesCaret.java @@ -0,0 +1,293 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Toolkit; +import java.awt.datatransfer.StringSelection; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Highlighter; +import javax.swing.text.NavigationFilter; +import javax.swing.text.Position; + +import org.scilab.modules.commons.gui.ScilabCaret; + +/** + * SciNotesCaret Class + * @author Calixte DENIZET + */ +public class SciNotesCaret extends ScilabCaret { + + private static final long serialVersionUID = 2406847391415867003L; + + private ScilabEditorPane pane; + private SciNotesNavigationFilter filter; + private NavigationFilter saveFilter; + + private List<Object> selections = new ArrayList<Object>(); + private int[][] positions; + private boolean protect; + + /** + * Constructor + * @param pane the pane where the caret is displayed + */ + public SciNotesCaret(ScilabEditorPane pane) { + super(pane); + this.pane = pane; + } + + public void clean() { + pane = null; + filter = null; + saveFilter = null; + selections = null; + positions = null; + } + + /** + * @param protect true to avoid the highlight removal + */ + public void protectHighlights(boolean protect) { + this.protect = protect; + } + + /** + * Update the highlights considering the new positions + */ + public void updateHighlights() { + Highlighter h = pane.getHighlighter(); + try { + for (int i = 0; i < positions.length; i++) { + Object obj = selections.get(i); + if (obj != null) { + h.changeHighlight(obj, positions[i][0], positions[i][1]); + } + } + } catch (BadLocationException e) { + System.err.println(e); + } + } + + /** + * @return the positions of the column selection or null + */ + public int[][] getSelectedPositions() { + return positions; + } + + /** + * @return the positions of the column selection or null + */ + public List<Object> getSelections() { + return selections; + } + + /** + * @return true if something has been removed + */ + public boolean removePositions() { + int[][] pos = positions; + if (pos != null) { + Document doc = pane.getDocument(); + try { + int slen = 0; + int len; + for (int i = 0; i < pos.length; i++) { + len = pos[i][1] - pos[i][0]; + doc.remove(pos[i][0] - slen, len); + slen += len; + } + } catch (BadLocationException e) { + System.err.println(e); + } + } + + return pos != null; + } + + /** + * @return the selected text in column mode + */ + public String getSelectedText() { + if (positions != null) { + try { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < positions.length; i++) { + buf.append(pane.getText(positions[i][0], positions[i][1] - positions[i][0])); + if (i < positions.length - 1) { + buf.append("\n"); + } + } + + return buf.toString(); + } catch (BadLocationException e) { + System.err.println(e); + } + } + + return null; + } + + /** + * @return true if the column selection is empty + */ + public boolean isEmptySelection() { + return positions == null; + } + + /** + * @return true if something has been copied in the clipboard + */ + public boolean copyPositionsInClipboard() { + if (positions != null) { + StringSelection sel = new StringSelection(getSelectedText()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, sel); + } + + return positions != null; + } + + /** + * {@inheritDoc} + */ + public void mouseReleased(MouseEvent e) { + if (filter != null) { + filter = null; + pane.setNavigationFilter(saveFilter); + } + super.mouseReleased(e); + } + + /** + * {@inheritDoc} + */ + public void mouseDragged(MouseEvent e) { + if (!e.isConsumed() && SwingUtilities.isLeftMouseButton(e)) { + if (e.isControlDown()) { + if (filter == null) { + filter = new SciNotesNavigationFilter(); + saveFilter = pane.getNavigationFilter(); + pane.setNavigationFilter(filter); + } + } else if (filter != null) { + filter = null; + pane.setNavigationFilter(saveFilter); + } + + super.mouseDragged(e); + } + } + + /** + * Remove the highlights + */ + public void removeHighlights() { + if (!protect) { + Highlighter h = pane.getHighlighter(); + for (Object obj : selections) { + if (obj != null) { + h.removeHighlight(obj); + } + } + selections.clear(); + positions = null; + } + } + + /** + * {@inheritDoc} + */ + public void setDot(int dot, Position.Bias dotBias) { + removeHighlights(); + super.setDot(dot, dotBias); + } + + /** + * Inner class to specify the portion of the text to select in column mode. + */ + class SciNotesNavigationFilter extends NavigationFilter { + + private int mark = -1; + private Element root = pane.getDocument().getDefaultRootElement(); + + /** + * Constructor + */ + public SciNotesNavigationFilter() { + super(); + } + + /** + * {@inheritDoc} + */ + public void moveDot(NavigationFilter.FilterBypass fb, int sdot, Position.Bias bias) { + int dot = sdot; + if (mark == -1) { + mark = --dot; + } + + pane.setCaretPosition(dot); + + if (isSelectionVisible()) { + Highlighter h = pane.getHighlighter(); + if (h != null) { + int p0 = Math.min(dot, mark); + int p1 = Math.max(dot, mark); + + if (!selections.isEmpty()) { + removeHighlights(); + } + + int startL = root.getElementIndex(p0); + int endL = root.getElementIndex(p1); + int sC = p0 - root.getElement(startL).getStartOffset(); + int eC = p1 - root.getElement(endL).getStartOffset(); + int startC = Math.min(sC, eC); + int endC = Math.max(sC, eC); + + Highlighter.HighlightPainter p = getSelectionPainter(); + int delta = endC - startC; + + if (p0 != p1) { + positions = new int[endL - startL + 1][2]; + + try { + for (int i = startL; i <= endL; i++) { + Element elem = root.getElement(i); + int end = elem.getEndOffset(); + int index = i - startL; + p1 = Math.min(p0 + delta, end); + positions[index][0] = Math.min(elem.getStartOffset() + startC, end); + positions[index][1] = Math.min(positions[index][0] + delta, end); + if (positions[index][0] < positions[index][1]) { + selections.add(h.addHighlight(positions[index][0], positions[index][1], p)); + } else { + selections.add(null); + } + } + } catch (BadLocationException e) { + System.err.println(e); + } + } + } + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesConfiguration.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesConfiguration.java new file mode 100755 index 000000000..33e911fdc --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesConfiguration.java @@ -0,0 +1,74 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.util.Set; + +import org.scilab.modules.commons.xml.XConfigurationEvent; +import org.scilab.modules.commons.xml.XConfigurationListener; + +public class SciNotesConfiguration implements XConfigurationListener { + + public SciNotesConfiguration() { } + + /** + * Prevent the listener that configuration has changed + * + * @param e the event + */ + public void configurationChanged(XConfigurationEvent e) { + Conf conf = new Conf(e.getModifiedPaths()); + if (conf.changed()) { + SciNotesOptions.invalidate(conf); + SciNotes.configurationChanged(conf); + } + } + + public static class Conf { + + public boolean preferences; + public boolean display; + public boolean autosave; + public boolean colors; + public boolean systemfont; + public boolean font; + public boolean keymap; + public boolean header; + + public Conf(Set<String> path) { + if (path.contains("ALL")) { + preferences = true; + display = true; + autosave = true; + colors = true; + systemfont = true; + font = true; + keymap = true; + header = true; + } else { + preferences = path.contains(SciNotesOptions.PREFERENCESPATH); + display = path.contains(SciNotesOptions.DISPLAYPATH); + autosave = path.contains(SciNotesOptions.AUTOSAVEPATH); + colors = path.contains(ScilabContext.COLORSPATH); + systemfont = path.contains(ScilabContext.SYSTEMFONTPATH); + font = path.contains(ScilabContext.XCONFFONTPATH); + keymap = path.contains(SciNotesOptions.KEYMAPPATH); + header = path.contains(SciNotesOptions.HEADERPATH); + } + } + + public boolean changed() { + return preferences || display || autosave || colors || systemfont || font || keymap || header; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesGUI.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesGUI.java new file mode 100755 index 000000000..86ca9b042 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesGUI.java @@ -0,0 +1,385 @@ +/* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.JButton; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.scilab.modules.commons.gui.ScilabLAF; +import org.scilab.modules.commons.xml.ScilabDocumentBuilderFactory; +import org.scilab.modules.gui.bridge.checkboxmenuitem.SwingScilabCheckBoxMenuItem; +import org.scilab.modules.gui.bridge.menu.SwingScilabMenu; +import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem; +import org.scilab.modules.gui.bridge.toolbar.SwingScilabToolBar; +import org.scilab.modules.gui.bridge.window.SwingScilabWindow; +import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.menubar.MenuBar; +import org.scilab.modules.gui.menubar.ScilabMenuBar; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.textbox.ScilabTextBox; +import org.scilab.modules.gui.textbox.TextBox; +import org.scilab.modules.gui.toolbar.ScilabToolBar; +import org.scilab.modules.gui.toolbar.ToolBar; +import org.scilab.modules.localization.Messages; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * Class SciNotesGUI handles menus, bar, ... + */ +public final class SciNotesGUI { + + private static final String MENU_CONF = System.getenv("SCI") + "/modules/scinotes/etc/scinotesGUIConfiguration.xml"; + private static final String ERROR_READ = "Could not load file: "; + private static final String MENUBAR = "MenuBar"; + private static final String TOOLBAR = "ToolBar"; + private static final String RIGHTCLICKMENU = "RightClickMenu"; + private static final String MENU = "menu"; + private static final String MNEMONIC = "mnemonic"; + private static final String LABEL = "label"; + private static final String MENUITEM = "menuitem"; + private static final String ACTION = "action"; + private static final String SEPARATOR = "separator"; + private static final String TOOLTIP = "tooltip"; + private static final String ICON = "icon"; + private static final String BUTTON = "button"; + private static final String DOT = "."; + + private static final String DEFAULTACTIONPATH = "org.scilab.modules.scinotes.actions"; + + private static Document menuConf; + + private static Map<SciNotes, MenuBar> mapMenuBar = new HashMap<SciNotes, MenuBar>(); + private static Map<SciNotes, ToolBar> mapToolBar = new HashMap<SciNotes, ToolBar>(); + private static Map<SciNotes, JPopupMenu> mapPopup = new HashMap<SciNotes, JPopupMenu>(); + private static Map<SciNotes, TextBox> mapInfoBar = new HashMap<SciNotes, TextBox>(); + + /** + * initialize the window + * @param mainWindow Windows + * @param editorInstance SciNotes + * @param title the title + */ + public static void init(SwingScilabWindow mainWindow, final SciNotes editorInstance, String title) { + mainWindow.setTitle(title); + mainWindow.addTab(editorInstance); + + // Set SciNotes Window position /size + mainWindow.setTitle(title); + mainWindow.setVisible(true); + + init(editorInstance); + } + + /** + * Initialize SciNotes + * @param editorInstance SciNotes + */ + public static void init(SciNotes editorInstance) { + editorInstance.setMenuBar(generateMenuBar(editorInstance)); + editorInstance.setToolBar(generateToolBar(editorInstance)); + editorInstance.setInfoBar(generateInfoBar(editorInstance)); + } + + public static void clean(SciNotes editorInstance) { + mapMenuBar.remove(editorInstance); + mapToolBar.remove(editorInstance); + mapPopup.remove(editorInstance); + mapInfoBar.remove(editorInstance); + } + + /** + * Initialize SciNotes + * @param editorInstance SciNotes + */ + public static void reinitMenus(SciNotes editorInstance) { + mapMenuBar.remove(editorInstance); + mapPopup.remove(editorInstance); + editorInstance.setMenuBar(generateMenuBar(editorInstance)); + } + + /** + * @param editor the editor + * @return the infobar of the editor + */ + public static TextBox generateInfoBar(SciNotes editor) { + if (mapInfoBar.containsKey(editor)) { + return mapInfoBar.get(editor); + } + + TextBox info = ScilabTextBox.createTextBox(); + mapInfoBar.put(editor, info); + + return info; + } + + /** + * @param editor the editor + * @return the JPopupMenu read in the conf file + */ + public static JPopupMenu generateRightClickPopup(SciNotes editor) { + if (mapPopup.containsKey(editor)) { + return mapPopup.get(editor); + } + + readMenusConf(); + JPopupMenu popup = new JPopupMenu(); + Element root = menuConf.getDocumentElement(); + Element rightmenu = (Element) root.getElementsByTagName(RIGHTCLICKMENU).item(0); + NodeList menus = rightmenu.getChildNodes(); + for (int i = 0; i < menus.getLength(); i++) { + Node item = menus.item(i); + if (MENUITEM.equals(item.getNodeName())) { + Element elem = (Element) item; + Object menuitem = getMenuItem(elem.getAttribute(ACTION), elem.getAttribute(LABEL), editor); + if (menuitem != null) { + if (menuitem instanceof CheckBoxMenuItem) { + SwingScilabCheckBoxMenuItem checkbox = (SwingScilabCheckBoxMenuItem) ((CheckBoxMenuItem) menuitem).getAsSimpleCheckBoxMenuItem(); + popup.add(checkbox); + } else if (menuitem instanceof MenuItem) { + SwingScilabMenuItem smi = (SwingScilabMenuItem) ((MenuItem) menuitem).getAsSimpleMenuItem(); + popup.add(smi); + } else if (menuitem instanceof Menu) { + SwingScilabMenu sm = (SwingScilabMenu) ((Menu) menuitem).getAsSimpleMenu(); + popup.add(sm); + } + } + } else if (SEPARATOR.equals(item.getNodeName())) { + popup.addSeparator(); + } else if (MENU.equals(item.getNodeName())) { + SwingScilabMenu sm = (SwingScilabMenu) getMenu(editor, (Element) item).getAsSimpleMenu(); + popup.add(sm); + } + } + mapPopup.put(editor, popup); + + return popup; + } + + /** + * @param editor the editor + * @return the ToolBar read in the conf file + */ + public static ToolBar generateToolBar(SciNotes editor) { + if (mapToolBar.containsKey(editor)) { + return mapToolBar.get(editor); + } + + readMenusConf(); + ToolBar toolBar = ScilabToolBar.createToolBar(); + Element root = menuConf.getDocumentElement(); + Element toolbar = (Element) root.getElementsByTagName(TOOLBAR).item(0); + NodeList buttons = toolbar.getChildNodes(); + for (int i = 0; i < buttons.getLength(); i++) { + Node node = buttons.item(i); + if (BUTTON.equals(node.getNodeName())) { + Element elem = (Element) node; + JButton button = getButton(elem.getAttribute(ACTION), elem.getAttribute(TOOLTIP), elem.getAttribute(ICON), editor); + ((SwingScilabToolBar) toolBar.getAsSimpleToolBar()).add(button); + } else if (SEPARATOR.equals(node.getNodeName())) { + toolBar.addSeparator(); + } + } + mapToolBar.put(editor, toolBar); + + return toolBar; + } + + /** + * @param editor the editor + * @return the MenuBar read in the conf file + */ + public static MenuBar generateMenuBar(SciNotes editor) { + if (mapMenuBar.containsKey(editor)) { + return mapMenuBar.get(editor); + } + + readMenusConf(); + MenuBar menuBar = ScilabMenuBar.createMenuBar(); + Element root = menuConf.getDocumentElement(); + Element menubar = (Element) root.getElementsByTagName(MENUBAR).item(0); + NodeList menus = menubar.getChildNodes(); + for (int i = 0; i < menus.getLength(); i++) { + Node node = menus.item(i); + if (MENU.equals(node.getNodeName())) { + menuBar.add(getMenu(editor, (Element) node)); + } + } + mapMenuBar.put(editor, menuBar); + + return menuBar; + } + + /** + * Read the conf file + */ + private static void readMenusConf() { + File xml = null; + DocumentBuilder docBuilder = null; + + try { + if (menuConf == null) { + DocumentBuilderFactory factory = ScilabDocumentBuilderFactory.newInstance(); + docBuilder = factory.newDocumentBuilder(); + xml = new File(MENU_CONF); + menuConf = docBuilder.parse(xml); + } + } catch (ParserConfigurationException pce) { + System.err.println(ERROR_READ + MENU_CONF); + } catch (SAXException se) { + System.err.println(ERROR_READ + MENU_CONF); + } catch (IOException ioe) { + System.err.println(ERROR_READ + MENU_CONF); + } + } + + /** + * @param editor the editor + * @param node the node containing the information + * @return the Menu + */ + private static Menu getMenu(SciNotes editor, Element node) { + Menu menu = ScilabMenu.createMenu(); + menu.setText(Messages.gettext(node.getAttribute(LABEL))); + String mnemonic = node.getAttribute(MNEMONIC); + if (mnemonic != null && mnemonic.length() != 0) { + menu.setMnemonic(mnemonic.charAt(0)); + } + NodeList elements = node.getChildNodes(); + for (int i = 0; i < elements.getLength(); i++) { + Node item = elements.item(i); + if (MENUITEM.equals(item.getNodeName())) { + Element elem = (Element) item; + Object menuitem = getMenuItem(elem.getAttribute(ACTION), elem.getAttribute(LABEL), editor); + if (menuitem != null) { + if (menuitem instanceof CheckBoxMenuItem) { + menu.add((CheckBoxMenuItem) menuitem); + } else if (menuitem instanceof MenuItem) { + menu.add((MenuItem) menuitem); + } else if (menuitem instanceof Menu) { + menu.add((Menu) menuitem); + } + } + } else if (SEPARATOR.equals(item.getNodeName())) { + menu.addSeparator(); + } else if (MENU.equals(item.getNodeName())) { + menu.add(getMenu(editor, (Element) item)); + } + } + + return menu; + } + + /** + * @param action a string with the action associated with the button + * @param label the title of the menu + * @param editor the editor + * @return a MenuItem or a CheckBoxMenuItem or a Menu + */ + private static Object getMenuItem(String action, String label, SciNotes editor) { + ClassLoader loader = ClassLoader.getSystemClassLoader(); + String className = ""; + Method method = null; + String actionClass = SciNotes.getActionName().get(action); + try { + if (action.lastIndexOf(DOT) != -1) { + className = actionClass; + } else { + className = DEFAULTACTIONPATH + DOT + actionClass; + } + Class clazz = loader.loadClass(className); + method = clazz.getMethod("createMenu", new Class[] {String.class, SciNotes.class, KeyStroke.class}); + } catch (ClassNotFoundException e) { + System.err.println("No action: " + className); + } catch (NoSuchMethodException e) { + System.err.println("No valid method createMenu in action: " + className); + } + + if (method == null) { + return null; + } + + try { + return method.invoke(null, new Object[] {Messages.gettext(label), editor, SciNotes.getActionKeys().get(action)}); + } catch (InvocationTargetException e) { + System.err.println("Warning: problem to create the menu for action: " + className); + System.err.println("The menu label is: " + Messages.gettext(label)); + System.err.println("English version will be used instead."); + System.err.println("Please report a bug at: http://bugzilla.scilab.org"); + try { + return method.invoke(null, new Object[] {label, editor, SciNotes.getActionKeys().get(action)}); + } catch (InvocationTargetException ex) { + System.err.println("Problem to create menu of the action: " + className); + } catch (IllegalAccessException ex) { + System.err.println("The method createMenu must be public: " + className); + } + } catch (IllegalAccessException e) { + System.err.println("The method createMenu must be public: " + className); + } + + return null; + } + + /** + * @param action a string with the action associated with the button + * @param tooltip a string with the tooltip + * @param icon the icon name + * @param editor the editor + * @return the button + */ + private static JButton getButton(String action, String tooltip, String icon, SciNotes editor) { + ClassLoader loader = ClassLoader.getSystemClassLoader(); + String className = ""; + String actionClass = SciNotes.getActionName().get(action); + try { + if (action.lastIndexOf(DOT) != -1) { + className = actionClass; + } else { + className = DEFAULTACTIONPATH + DOT + actionClass; + } + Class clazz = loader.loadClass(className); + Method method = clazz.getMethod("createButton", new Class[] {String.class, String.class, SciNotes.class}); + JButton button = (JButton) method.invoke(null, new Object[] {Messages.gettext(tooltip), icon, editor}); + ScilabLAF.setDefaultProperties(button); + + return button; + } catch (ClassNotFoundException e) { + System.err.println("No action: " + className); + } catch (NoSuchMethodException e) { + System.err.println("No valid method createButton in action: " + className); + } catch (IllegalAccessException e) { + System.err.println("The method createButton must be public: " + className); + } catch (InvocationTargetException e) { + System.err.println("The method createButton in " + className + " threw an exception :"); + e.printStackTrace(); + } + + return null; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesLineNumberPanel.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesLineNumberPanel.java new file mode 100755 index 000000000..97a2eaec7 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesLineNumberPanel.java @@ -0,0 +1,473 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Toolkit; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseEvent; +import java.util.Map; +import java.util.Stack; + +import javax.swing.JPanel; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.MatteBorder; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Element; +import javax.swing.text.View; + +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * This class will display line numbers for a related text component. The text + * component must use the same line height for each line. TextLineNumber + * supports wrapped lines and will highlight the line number of the current + * line in the text component. + * + * This class was designed to be used as a component added to the row header + * of a JScrollPane. + * @author Calixte DENIZET + */ +public class SciNotesLineNumberPanel extends JPanel implements CaretListener, DocumentListener, MouseMotionListener { + + private static final long serialVersionUID = -5302189665896954438L; + private static final int PANELGAPSIZE = 10; + private static final Border OUTER = new MatteBorder(0, 0, 0, 2, Color.GRAY); + private static final int HEIGHT = Integer.MAX_VALUE - 1000000; + private static Map desktopFontHints; + + private ScilabEditorPane textPane; + + private Color currentLineForeground; + private Color foreground = Color.BLACK; + private Color anchorColor = new Color(250, 251, 164); + private Color alternColor1 = new Color(246, 191, 246); + private Color alternColor2 = new Color(246, 101, 246); + + private int numbers = 1; + private int lastLine; + private int state; + + private ScilabDocument doc; + private FontMetrics metrics; + private int ascent; + private int availableWidth; + + private int[] lineNumber; + private byte[] lineLevel; + private boolean whereami; + private boolean display; + + /** + * Create a line number component for a text component. + * @param textPane the related text component + */ + public SciNotesLineNumberPanel(ScilabEditorPane textPane) { + this.textPane = textPane; + this.doc = (ScilabDocument) textPane.getDocument(); + setOpaque(true); + updateFont(textPane.getFont()); + setBorderGap(PANELGAPSIZE); + setCurrentLineForeground(Color.RED); + setAlternColors(ConfigSciNotesManager.getAlternColors()); + textPane.addCaretListener(this); + addMouseMotionListener(this); + } + + /** + * Set a line numbering compatible with the whereami function + * @param state 0 for nothing, 1 for normal and 2 for whereami + */ + public void setWhereamiLineNumbering(int state) { + if (state != this.state) { + if (state != 0) { + if (!display) { + textPane.getScrollPane().setRowHeaderView(this); + } + whereami = state == 2; + display = true; + } else { + textPane.getScrollPane().setRowHeaderView(null); + display = false; + } + updateLineNumber(); + this.state = state; + } + } + + public static int getState(boolean showLinesNumber, boolean whereami) { + if (!showLinesNumber) { + return 0; + } else if (!whereami) { + return 1; + } else { + return 2; + } + } + + public static boolean[] getState(int state) { + switch (state) { + case 0: + return new boolean[] { false, false }; + case 1: + return new boolean[] { true, false }; + case 2: + return new boolean[] { true, true }; + default: + return null; + } + } + + /** + * Set a line numbering compatible with the whereami function + * @param state 0 for nothing, 1 for normal and 2 for whereami + */ + public void setWhereamiLineNumbering(boolean showLinesNumber, boolean whereami) { + setWhereamiLineNumbering(getState(showLinesNumber, whereami)); + } + + /** + * Get the number of the lines used in the panel + * @return the lines number depending on whereami mode or none + */ + public int[] getLineNumber() { + int[] ret = null; + if (display) { + if (whereami) { + updateLineNumber(); + ret = lineNumber; + } else { + ret = new int[doc.getDefaultRootElement().getElementCount()]; + for (int i = 0; i < ret.length; i++) { + ret[i] = i + 1; + } + } + } + + return ret; + } + + /** + * @return the current state + */ + public int getState() { + return state; + } + + /** + * @return true if whereami-compatible + */ + public boolean getWhereamiLineNumbering() { + return whereami; + } + + /** + * @param colors an array of size 2 containing the two alternative colors for inner function + */ + public void setAlternColors(Color[] colors) { + if (colors[0] == null) { + this.alternColor1 = getBackground(); + } else { + this.alternColor1 = colors[0]; + } + if (colors[1] == null) { + this.alternColor2 = getBackground(); + } else { + this.alternColor2 = colors[1]; + } + } + + /** + * Update the font used in this component + * @param font the font to use + */ + public void updateFont(Font font) { + setFont(font); + metrics = textPane.getFontMetrics(font); + ascent = metrics.getAscent(); + updateWidth(false); + } + + /** + * Gets the current line rendering Color + * + * @return the Color used to render the current line number + */ + public Color getCurrentLineForeground() { + if (currentLineForeground == null) { + return getForeground(); + } else { + return currentLineForeground; + } + } + + /** + * The Color used to render the current line numbers. Default is Coolor.RED. + * + * @param currentLineForeground the Color used to render the current line + */ + public void setCurrentLineForeground(Color currentLineForeground) { + this.currentLineForeground = currentLineForeground; + } + + /** + * Update the width of this component in using the number of digits used + */ + public void updateWidth(boolean inc) { + if (inc) { + ++numbers; + } + Insets insets = getInsets(); + int width = metrics.charWidth('0') * numbers; + availableWidth = width; + Dimension d = getPreferredSize(); + d.setSize(availableWidth, HEIGHT); + availableWidth = width; + setPreferredSize(d); + setSize(d); + } + + /** + * Draw the line numbers + * @param g the graphics where to paint + */ + public void paintComponent(Graphics g) { + super.paintComponent(g); + + if (desktopFontHints == null) { + desktopFontHints = (Map) (Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); + } else { + ((Graphics2D) g).addRenderingHints(desktopFontHints); + } + + synchronized (doc) { + Element root = doc.getDefaultRootElement(); + View view = doc.getView(); + Rectangle clip = g.getClipBounds(); + Point pt = new Point(0, clip.y); + int rowStartOffset = textPane.viewToModel(pt); + pt.y += clip.height; + int endOffset = textPane.viewToModel(pt); + int lineEnd = root.getElementIndex(endOffset); + boolean colorChanged; + + for (int line = root.getElementIndex(rowStartOffset); line <= lineEnd; line++) { + String str; + colorChanged = false; + if (whereami && lineNumber != null) { + if (lineNumber[line] != -1) { + str = Integer.toString(lineNumber[line]); + if ((lineLevel[line] % 3) == 1) { + g.setColor(alternColor1); + colorChanged = true; + } else if ((lineLevel[line] % 3) == 2) { + g.setColor(alternColor2); + colorChanged = true; + } + } else { + str = ""; + } + } else { + str = Integer.toString(line + 1); + } + + Element elem = root.getElement(line); + if (((ScilabDocument.ScilabLeafElement) elem).isAnchor()) { + g.setColor(anchorColor); + colorChanged = true; + } + + if (colorChanged) { + if (view instanceof ScilabView) { + g.fillRect(0, ((ScilabView) view).getLineAllocation(line), availableWidth, metrics.getHeight()); + } else { + g.fillRect(0, ((ScilabPlainView) view).getLineAllocation(line), availableWidth, metrics.getHeight()); + } + } + + if (line != lastLine) { + g.setColor(foreground); + } else { + g.setColor(currentLineForeground); + } + + int diff = (availableWidth - metrics.stringWidth(str)) / 2; + if (diff <= 0) { + updateWidth(true); + diff = (availableWidth - metrics.stringWidth(str)) / 2; + } + + if (view instanceof ScilabView) { + g.drawString(str, diff, ((ScilabView) view).getLineAllocation(line) + ascent); + } else { + g.drawString(str, diff, ((ScilabPlainView) view).getLineAllocation(line) + ascent); + } + } + } + } + + /** + * Update this component if the caret changed of line + * @param e the event + */ + public void caretUpdate(CaretEvent e) { + Element root = doc.getDefaultRootElement(); + int currentLine = root.getElementIndex(textPane.getCaretPosition()); + + if (lastLine != currentLine) { + lastLine = currentLine; + repaint(); + } + } + + /** + * Useful method to determinate the number of the lines in being compatible + * with the whereami function + */ + private void updateLineNumber() { + synchronized (doc) { + Stack<Integer> stk = new Stack<Integer>(); + Element root = doc.getDefaultRootElement(); + int nlines = root.getElementCount(); + lineNumber = new int[nlines + 1]; + lineLevel = new byte[nlines + 1]; + lineNumber[0] = 1; + int current = 1; + boolean prevBroken = false; + ScilabDocument.ScilabLeafElement elem; + for (int i = 0; i < nlines; i++) { + elem = (ScilabDocument.ScilabLeafElement) root.getElement(i); + int type = elem.getType(); + switch (type) { + case ScilabDocument.ScilabLeafElement.NOTHING : + if (prevBroken) { + lineNumber[i] = -1; + if (!elem.isBroken()) { + prevBroken = false; + } + } else { + lineNumber[i] = current++; + } + lineLevel[i] = (byte) stk.size(); + break; + case ScilabDocument.ScilabLeafElement.FUN : + stk.push(new Integer(current)); + lineLevel[i] = (byte) stk.size(); + current = 2; + lineNumber[i] = 1; + if (elem.isBroken()) { + prevBroken = true; + } + break; + case ScilabDocument.ScilabLeafElement.ENDFUN : + lineNumber[i] = current++; + lineLevel[i] = (byte) stk.size(); + if (!stk.empty()) { + current = stk.pop().intValue() + lineNumber[i]; + } + break; + default : + break; + } + } + } + } + + /** + * Implements mouseMoved in MouseMotionListener + * @param e event + */ + public void mouseMoved(MouseEvent e) { + int pos = textPane.viewToModel(e.getPoint()); + Element root = doc.getDefaultRootElement(); + ScilabDocument.ScilabLeafElement line = (ScilabDocument.ScilabLeafElement) root.getElement(root.getElementIndex(pos)); + if (line.isAnchor()) { + setToolTipText(SciNotesMessages.ANCHOR + line.toString()); + } else { + setToolTipText(null); + } + } + + /** + * Nothing ! + * @param e event + */ + public void mouseDragged(MouseEvent e) { } + + /** + * Nothing ! + * @param e the event + */ + public void changedUpdate(DocumentEvent e) { } + + /** + * Called when an insertion is made in the doc + * @param e the event + */ + public void insertUpdate(DocumentEvent e) { + handleEvent(e); + } + + /** + * Called when a remove is made in the doc + * @param e the event + */ + public void removeUpdate(DocumentEvent e) { + handleEvent(e); + } + + /** + * Update the line numbering on a change in the document + * @param e the document event + */ + private void handleEvent(DocumentEvent e) { + if (whereami) { + Element root = doc.getDefaultRootElement(); + DocumentEvent.ElementChange chg = e.getChange(root); + if (chg == null) { + // change occurred only in one line + ScilabDocument.ScilabLeafElement line = (ScilabDocument.ScilabLeafElement) root.getElement(root.getElementIndex(e.getOffset())); + if (line.needLineNumberRepaint()) { + updateLineNumber(); + repaint(); + } + } else { + updateLineNumber(); + } + } + } + + /** + * The border gap is used in calculating the left and right insets of the + * border. Default value is 5. + * @param borderGap the gap in pixels + */ + private void setBorderGap(int borderGap) { + Border inner = new EmptyBorder(0, borderGap, 0, borderGap); + setBorder(new CompoundBorder(OUTER, inner)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesOptions.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesOptions.java new file mode 100755 index 000000000..1b04857a5 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SciNotesOptions.java @@ -0,0 +1,297 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2012 - Scilab Enterprises -Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Color; +import java.text.DateFormat; +import java.util.Calendar; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; + +import org.scilab.modules.commons.OS; +import static org.scilab.modules.commons.xml.XConfiguration.XConfAttribute; +import org.scilab.modules.commons.xml.XConfiguration; + +/** + * The class ScilabContext provides a context to render a Scilab's document. + * @author Calixte DENIZET + */ +public class SciNotesOptions { + + public static final String PREFERENCESPATH = "//scinotes/body/scinotes-preferences"; + public static final String DISPLAYPATH = "//scinotes/display/body/scinotes-display"; + public static final String AUTOSAVEPATH = "//scinotes/autosave/body/scinotes-autosave"; + public static final String HEADERPATH = "//scinotes/header/body/scinotes-header"; + public static final String KEYMAPPATH = "//general/shortcuts/body/actions/action-folder[@xconf-uid=\"scinotes\"]/action"; + + private static SciNotesOptions.Preferences prefs; + private static SciNotesOptions.Display display; + private static SciNotesOptions.Autosave autosave; + private static SciNotesOptions.Header header; + + private static Document doc; + + /* scinotes-preferences */ + @XConfAttribute + public static class Preferences { + + public boolean restartOpen; + public boolean addLineTermination; + public int numberOfRecentlyOpen; + public String encoding; + public String eol; + public boolean useScinotes; + public boolean externalCmd; + public String cmd; + public boolean completeAtEOL; + + private Preferences() { } + + @XConfAttribute(tag = "scinotes-preferences", attributes = {"restart-reopen", "add-line-termination", "number-of-recently-open", "encoding", "eol", "scinotes", "cmd", "external-cmd", "complete-at-eol"}) + private void set(boolean restartOpen, boolean addLineTermination, int numberOfRecentlyOpen, String encoding, String eol, boolean useScinotes, String cmd, boolean externalCmd, boolean completeAtEOL) { + this.restartOpen = restartOpen; + this.addLineTermination = addLineTermination; + this.numberOfRecentlyOpen = numberOfRecentlyOpen > 0 ? numberOfRecentlyOpen : 1; + this.encoding = encoding.toLowerCase(); + + if (eol.equals("")) { + switch (OS.get()) { + case WINDOWS: + this.eol = ScilabDocument.EOLWIN; + break; + default: + this.eol = ScilabDocument.EOLUNIX; + break; + } + } else if (eol.startsWith("Windows")) { + this.eol = ScilabDocument.EOLWIN; + } else { + this.eol = ScilabDocument.EOLUNIX; + } + + this.useScinotes = useScinotes; + this.externalCmd = externalCmd; + this.cmd = cmd; + this.completeAtEOL = completeAtEOL; + } + } + + /* scinotes-display */ + @XConfAttribute + public static class Display { + + public boolean highlightCurrentLine; + public Color currentLineColor; + public boolean showLineNumbers; + public boolean wrapLines; + public boolean keywordsColorization; + public boolean highlightBrackets; + public Color bracketsColor; + public int bracketsHighlightment; + public boolean bracketsOnmouseover; + public boolean highlightKeywords; + public Color keywordsColor; + public int keywordsHighlightment; + public boolean keywordsOnmouseover; + public boolean whereami; + public int tabSize; + public int tabRepresentation; + public boolean useSpaces; + public int indentSize; + public boolean automaticIndent; + public boolean autoCompleteOpeners; + public boolean autoCompleteKeywords; + public Color backgroundColor; + public Color caretColor; + + private Display() { } + + @XConfAttribute(tag = "scinotes-display", attributes = {"highlight-current-line", "current-line-color", "show-line-numbers", "wrap-lines", "keywords-colorization", "highlight-brackets", "brackets-color", "brackets-highlightment", "brackets-onmouseover", "highlight-keywords", "keywords-color", "keywords-highlightment", "keywords-onmouseover", "whereami", "tab-size", "tab-representation", "use-spaces", "indent-size", "automatic-indent", "auto-complete-openers", "auto-complete-keywords", "background-color", "caret-color"}) + private void set(boolean highlightCurrentLine, Color currentLineColor, boolean showLineNumbers, boolean wrapLines, boolean keywordsColorization, boolean highlightBrackets, Color bracketsColor, String bracketsHighlightment, boolean bracketsOnmouseover, boolean highlightKeywords, Color keywordsColor, String keywordsHighlightment, boolean keywordsOnmouseover, boolean whereami, int tabSize, String tabRepresentation, boolean useSpaces, int indentSize, boolean automaticIndent, boolean autoCompleteOpeners, boolean autoCompleteKeywords, Color backgroundColor, Color caretColor) { + this.highlightCurrentLine = highlightCurrentLine; + this.currentLineColor = currentLineColor; + this.showLineNumbers = showLineNumbers; + this.wrapLines = wrapLines; + this.keywordsColorization = keywordsColorization; + + this.highlightBrackets = highlightBrackets; + this.bracketsColor = bracketsColor; + this.bracketsOnmouseover = bracketsOnmouseover; + this.highlightKeywords = highlightKeywords; + this.keywordsColor = keywordsColor; + this.keywordsOnmouseover = keywordsOnmouseover; + this.whereami = whereami; + this.tabSize = tabSize; + if (tabRepresentation.equalsIgnoreCase("chevrons")) { + this.tabRepresentation = ScilabView.TABDOUBLECHEVRONS; + } else if (tabRepresentation.equalsIgnoreCase("hrule")) { + this.tabRepresentation = ScilabView.TABHORIZONTAL; + } else if (tabRepresentation.equalsIgnoreCase("vrule")) { + this.tabRepresentation = ScilabView.TABVERTICAL; + } else { + this.tabRepresentation = ScilabView.TABNOTHING; + } + this.useSpaces = useSpaces; + this.indentSize = indentSize; + this.automaticIndent = automaticIndent; + + if (bracketsHighlightment.equalsIgnoreCase("filled")) { + this.bracketsHighlightment = MatchingBlockManager.ScilabKeywordsPainter.FILLED; + } else if (bracketsHighlightment.equalsIgnoreCase("framed")) { + this.bracketsHighlightment = MatchingBlockManager.ScilabKeywordsPainter.FRAMED; + } else { + this.bracketsHighlightment = MatchingBlockManager.ScilabKeywordsPainter.UNDERLINED; + } + + if (keywordsHighlightment.equalsIgnoreCase("filled")) { + this.keywordsHighlightment = MatchingBlockManager.ScilabKeywordsPainter.FILLED; + } else if (keywordsHighlightment.equalsIgnoreCase("framed")) { + this.keywordsHighlightment = MatchingBlockManager.ScilabKeywordsPainter.FRAMED; + } else { + this.keywordsHighlightment = MatchingBlockManager.ScilabKeywordsPainter.UNDERLINED; + } + + this.autoCompleteOpeners = autoCompleteOpeners; + this.autoCompleteKeywords = autoCompleteKeywords; + this.backgroundColor = backgroundColor; + this.caretColor = caretColor; + } + } + + /* scinotes-autosave */ + @XConfAttribute + public static class Autosave { + + public boolean autoSave; + public int saveEvery; + public boolean automaticDelete; + public boolean appendFilename; + public String appendWith; + public String replaceWith; + public boolean sourceFlag; + public String singleDirectory; + + private Autosave() { } + + @XConfAttribute(tag = "scinotes-autosave", attributes = {"enable", "save-every", "automatic-delete", "append-filename", "append-with", "replace-with", "source-flag", "single-directory"}) + private void set(boolean autoSave, int saveEvery, boolean automaticDelete, boolean appendFilename, String appendWith, String replaceWith, boolean sourceFlag, String singleDirectory) { + this.autoSave = autoSave; + this.saveEvery = saveEvery; + this.automaticDelete = automaticDelete; + this.appendFilename = appendFilename; + this.appendWith = appendWith; + this.replaceWith = replaceWith; + this.sourceFlag = sourceFlag; + this.singleDirectory = singleDirectory; + } + } + + /* scinotes-header */ + @XConfAttribute + public static class Header { + + public String header; + public boolean enable; + + @XConfAttribute(tag = "scinotes-header", attributes = {"enable"}) + private void set(boolean enable) { + this.enable = enable; + if (enable) { + XPathFactory xpathFactory = XPathFactory.newInstance(); + XPath xp = xpathFactory.newXPath(); + try { + header = (String) xp.compile("string(" + HEADERPATH + ")").evaluate(doc, XPathConstants.STRING); + } catch (XPathExpressionException e) { + System.err.println(e); + } + + if (header != null) { + Calendar cal = Calendar.getInstance(); + DateFormat dateFormat = DateFormat.getDateInstance(); + header = header.replaceAll("\\{\\$current-year\\}", Integer.toString(cal.get(Calendar.YEAR))); + header = header.replaceAll("\\{\\$current-date\\}", dateFormat.format(cal.getTime())); + } + } + } + } + + public static void invalidate(SciNotesConfiguration.Conf conf) { + if (conf.preferences) { + prefs = null; + doc = null; + } + if (conf.display) { + display = null; + doc = null; + } + if (conf.autosave) { + autosave = null; + doc = null; + } + if (conf.header) { + header = null; + doc = null; + } + } + + public static final SciNotesOptions.Preferences getSciNotesPreferences() { + if (prefs == null) { + if (doc == null) { + doc = XConfiguration.getXConfigurationDocument(); + } + prefs = XConfiguration.get(SciNotesOptions.Preferences.class, doc, PREFERENCESPATH)[0]; + } + + return prefs; + } + + public static final SciNotesOptions.Display getSciNotesDisplay() { + if (display == null) { + if (doc == null) { + doc = XConfiguration.getXConfigurationDocument(); + } + display = XConfiguration.get(SciNotesOptions.Display.class, doc, DISPLAYPATH)[0]; + } + + return display; + } + + public static final SciNotesOptions.Autosave getSciNotesAutosave() { + if (autosave == null) { + if (doc == null) { + doc = XConfiguration.getXConfigurationDocument(); + } + autosave = XConfiguration.get(SciNotesOptions.Autosave.class, doc, AUTOSAVEPATH)[0]; + } + + return autosave; + } + + public static final SciNotesOptions.Header getSciNotesHeader() { + if (header == null) { + if (doc == null) { + doc = XConfiguration.getXConfigurationDocument(); + } + + header = XConfiguration.get(SciNotesOptions.Header.class, doc, HEADERPATH)[0]; + } + + + return header; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabContext.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabContext.java new file mode 100755 index 000000000..641993a3f --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabContext.java @@ -0,0 +1,425 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * Copyright (C) 2011 - Scilab Enterprises -Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Color; +import java.awt.Font; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.swing.text.ViewFactory; +import javax.swing.text.View; +import javax.swing.text.Element; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import static org.scilab.modules.commons.xml.XConfiguration.XConfAttribute; + +import org.scilab.modules.commons.xml.XConfiguration; +import org.scilab.modules.gui.utils.ScilabFontUtils; + +/** + * The class ScilabContext provides a context to render a Scilab's document. + * @author Calixte DENIZET + */ +public class ScilabContext implements ViewFactory { + + public static final String COLORSPATH = "//colors/body/syntax-highlighting-colors/item"; + public static final String SYSTEMFONTPATH = "//fonts/body/fonts"; + public static final String FONTPATH = "//fonts/body/fonts/item"; + public static final String XCONFFONTPATH = "//fonts/body/fonts/item[@xconf-uid=\"scinotes-font\"]"; + + /** + * Contains the colors of the different tokens + */ + public Color[] tokenColors; + + /** + * Contains the fonts of the different tokens + */ + public Font[] tokenFonts; + + /** + * Contains the attrib (underline or stroke) of the different tokens + */ + public int[] tokenAttrib; + + private Font baseFont; + private boolean isDesktop; + private boolean compatible; + private FontInfo[] scinotesInfos; + private FontInfo[] desktopInfos; + + private View view; + private boolean plain; + private List<Integer> typeToDefault = new ArrayList<Integer>(); + + /** + * The constructor + */ + public ScilabContext() { + super(); + genAll(); + } + + /** + * Constructor + * @param plain boolean for a plain view + */ + public ScilabContext(boolean plain) { + this(); + this.plain = plain; + } + + + public static void saveFont(Font font) { + XPathFactory xpathFactory = XPathFactory.newInstance(); + XPath xp = xpathFactory.newXPath(); + NodeList nodes; + Document doc = XConfiguration.getXConfigurationDocument(); + + try { + nodes = (NodeList) xp.compile("//fonts/body/fonts/item[@xconf-uid='scinotes-font']").evaluate(doc, XPathConstants.NODESET); + } catch (XPathExpressionException e) { + System.err.println(e); + return; + } + + org.w3c.dom.Element e = (org.w3c.dom.Element) nodes.item(0); + e.setAttribute("desktop", "false"); + e.setAttribute("font-name", font.getName()); + e.setAttribute("font-size", Integer.toString(font.getSize())); + + XConfiguration.save(); + } + + /** + * @return the font used to render + */ + public Font getBaseFont() { + return baseFont; + } + + public void changeBaseFontSize(int n) { + float size = baseFont.getSize2D() + n; + baseFont = baseFont.deriveFont(size); + for (int i = 0; i < tokenFonts.length; i++) { + tokenFonts[i] = tokenFonts[i].deriveFont(size); + } + } + + public void configurationChanged(SciNotesConfiguration.Conf conf) { + boolean modified = false; + FontInfo[] scinotes = null; + FontInfo[] desktop = null; + Document doc = null; + if (conf.colors) { + genAll(); + modified = true; + } + + if (!modified && conf.font) { + doc = XConfiguration.getXConfigurationDocument(); + scinotes = XConfiguration.get(FontInfo.class, doc, FONTPATH + "[@name='Scinotes']"); + if (!scinotes[0].equals(scinotesInfos)) { + genAll(); + modified = true; + } + } + + if (!modified && conf.systemfont) { + doc = XConfiguration.getXConfigurationDocument(); + desktop = XConfiguration.get(FontInfo.class, doc, SYSTEMFONTPATH); + genAll(); + } + } + + public void genAll() { + tokenAttrib = new int[ScilabLexerConstants.NUMBEROFTOKENS]; + tokenColors = new Color[ScilabLexerConstants.NUMBEROFTOKENS]; + tokenFonts = new Font[ScilabLexerConstants.NUMBEROFTOKENS]; + + Document doc = XConfiguration.getXConfigurationDocument(); + desktopInfos = XConfiguration.get(FontInfo.class, doc, SYSTEMFONTPATH); + scinotesInfos = XConfiguration.get(FontInfo.class, doc, FONTPATH + "[@name='Scinotes']"); + Font font; + if (scinotesInfos[0].isDesktop()) { + font = desktopInfos[0].getFont(); + isDesktop = true; + } else { + font = scinotesInfos[0].getFont(); + isDesktop = false; + } + + if (font != baseFont) { + compatible = ScilabFontUtils.isAllStylesSameWidths(font); + baseFont = font; + } + + FontDecoration[] decorations = XConfiguration.get(FontDecoration.class, doc, COLORSPATH); + doc = null; + + for (FontDecoration deco : decorations) { + tokenAttrib[deco.getType()] = deco.getValue(); + tokenColors[deco.getType()] = deco.getColor(); + tokenFonts[deco.getType()] = compatible ? baseFont.deriveFont(deco.getFontFace()) : baseFont; + } + + // Default color and special case + typeToDefault.clear(); + for (int i = 0; i < tokenColors.length; i++) { + if (tokenColors[i] == null) { + tokenColors[i] = tokenColors[0]; + typeToDefault.add(i); + } + } + + /* Special case : Scilab's developers in comments */ + tokenColors[ScilabLexerConstants.AUTHORS] = tokenColors[ScilabLexerConstants.COMMENT]; + tokenColors[ScilabLexerConstants.OSKEYWORD] = tokenColors[ScilabLexerConstants.SKEYWORD]; + tokenColors[ScilabLexerConstants.ELSEIF] = tokenColors[ScilabLexerConstants.SKEYWORD]; + + // Default attributes + for (Integer i : typeToDefault) { + tokenAttrib[i] = tokenAttrib[0]; + } + tokenAttrib[ScilabLexerConstants.OSKEYWORD] = tokenAttrib[ScilabLexerConstants.SKEYWORD]; + tokenAttrib[ScilabLexerConstants.ELSEIF] = tokenAttrib[ScilabLexerConstants.SKEYWORD]; + + // Default fonts + for (int i = 0; i < tokenFonts.length; i++) { + if (tokenFonts[i] == null) { + tokenFonts[i] = tokenFonts[0]; + } + } + + /* Special case : Scilab's developers in comments */ + Font c = tokenFonts[ScilabLexerConstants.COMMENT]; + int style = c.getStyle(); + if (compatible) { + if (c.isBold()) { + tokenFonts[ScilabLexerConstants.AUTHORS] = c.deriveFont(style ^ Font.BOLD); + } else { + tokenFonts[ScilabLexerConstants.AUTHORS] = c.deriveFont(style | Font.BOLD); + } + } + + tokenFonts[ScilabLexerConstants.OSKEYWORD] = tokenFonts[ScilabLexerConstants.SKEYWORD]; + tokenFonts[ScilabLexerConstants.ELSEIF] = tokenFonts[ScilabLexerConstants.SKEYWORD]; + } + + /** + * Generate an attribute for a type of keyword + * @param keyword the name can be found in scinotesConfiguration.xml + * @param type the type to use + */ + public void genAttribute(String keyword, int type) { + tokenAttrib[ScilabLexerConstants.TOKENS.get(keyword)] = type; + tokenAttrib[ScilabLexerConstants.OSKEYWORD] = tokenAttrib[ScilabLexerConstants.SKEYWORD]; + tokenAttrib[ScilabLexerConstants.ELSEIF] = tokenAttrib[ScilabLexerConstants.SKEYWORD]; + if (ScilabLexerConstants.TOKENS.get(keyword) == ScilabLexerConstants.DEFAULT) { + for (Integer i : typeToDefault) { + tokenAttrib[i] = tokenAttrib[0]; + } + } + } + + /** + * Generate a color for a type of keyword + * @param name the name can be found in scinotesConfiguration.xml + * @param color the color to use + */ + public void genColors(String name, Color color) { + tokenColors[ScilabLexerConstants.TOKENS.get(name)] = color; + tokenColors[ScilabLexerConstants.AUTHORS] = tokenColors[ScilabLexerConstants.COMMENT]; + tokenColors[ScilabLexerConstants.OSKEYWORD] = tokenColors[ScilabLexerConstants.SKEYWORD]; + tokenColors[ScilabLexerConstants.ELSEIF] = tokenColors[ScilabLexerConstants.SKEYWORD]; + + if (ScilabLexerConstants.TOKENS.get(name) == ScilabLexerConstants.DEFAULT) { + for (Integer i : typeToDefault) { + tokenColors[i] = tokenColors[0]; + } + } + } + + /** + * Generate a font for a type of keyword + * @param name the name can be found in scinotesConfiguration.xml + * @param type the type to use + */ + public void genFont(String name, int type) { + Font font = tokenFonts[ScilabLexerConstants.TOKENS.get(name)]; + int style = font.getStyle(); + switch (type) { + case -2 : + font = font.deriveFont(style & ~Font.ITALIC); + break; + case -1 : + font = font.deriveFont(style & ~Font.BOLD); + break; + case 1 : + font = font.deriveFont(style | Font.BOLD); + break; + case 2 : + font = font.deriveFont(style | Font.ITALIC); + break; + default : + } + + tokenFonts[ScilabLexerConstants.TOKENS.get(name)] = font; + tokenFonts[ScilabLexerConstants.OSKEYWORD] = tokenFonts[ScilabLexerConstants.SKEYWORD]; + tokenFonts[ScilabLexerConstants.ELSEIF] = tokenFonts[ScilabLexerConstants.SKEYWORD]; + if (ScilabLexerConstants.TOKENS.get(name) == ScilabLexerConstants.DEFAULT) { + for (Integer i : typeToDefault) { + tokenFonts[i] = tokenFonts[0]; + } + } + } + + /** + * @return the view to use to render the document + */ + public View getCurrentView() { + return view; + } + + /** + * Create a view with a given element + * @param elem the Element to view + * @return the view associated with the element + */ + public View create(Element elem) { + if (plain) { + view = new ScilabPlainView(elem, this); + ((ScilabPlainView) view).setDefaultTabRepresentation(); + } else { + view = new ScilabView(elem, this); + ((ScilabView) view).setDefaultTabRepresentation(); + } + return view; + } + + /** + * Inner class to retrieve configuration elements from configuration file + */ + @XConfAttribute + private static class FontInfo { + + String fontname; + int fontsize; + boolean desktop; + + public FontInfo() { } + + @XConfAttribute(attributes = {"font-name", "font-size", "desktop"}) + public void set(String fontname, int fontsize, boolean desktop) { + this.fontname = fontname; + this.fontsize = fontsize; + this.desktop = desktop; + } + + public boolean isDesktop() { + return desktop; + } + + public Font getFont() { + return new Font(fontname, Font.PLAIN, fontsize); + } + + public boolean equals(Object o) { + if (o instanceof FontInfo) { + FontInfo f = (FontInfo) o; + return fontname.equals(f.fontname) && fontsize == f.fontsize && desktop == f.desktop; + } + + return false; + } + } + + /** + * Inner class to retrieve configuration elements from configuration file + */ + @XConfAttribute + private static class FontDecoration { + + private boolean underline; + private boolean strikeThrough; + private boolean bold; + private boolean italic; + private Color color; + private int type; + + public FontDecoration() { } + + @XConfAttribute(attributes = {"underline", "strike-through", "name", "italic", "color", "bold"}) + public void set(boolean underline, boolean strikeThrough, String name, boolean italic, Color color, boolean bold) { + this.underline = underline; + this.strikeThrough = strikeThrough; + this.type = ScilabLexerConstants.TOKENS.get(name); + this.color = color; + this.italic = italic; + this.bold = bold; + } + + public int getFontFace() { + int fontface = Font.PLAIN; + if (bold) { + fontface = fontface | Font.BOLD; + } + + if (italic) { + fontface = fontface | Font.ITALIC; + } + + return fontface; + } + + public Color getColor() { + return color; + } + + public int getValue() { + int value = 0; + if (underline) { + value += 1; + } + if (strikeThrough) { + value += 2; + } + + return value; + } + + public int getType() { + return type; + } + + public boolean equals(Object o) { + if (o instanceof FontDecoration) { + FontDecoration f = (FontDecoration) o; + return underline == f.underline && strikeThrough == f.strikeThrough && bold == f.bold && italic == f.italic && color.equals(f.color) && type == f.type; + } + + return false; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabDocument.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabDocument.java new file mode 100755 index 000000000..78a3e72ee --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabDocument.java @@ -0,0 +1,1118 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.nio.charset.Charset; + +import java.util.Vector; +import java.util.ArrayList; +import java.util.List; +import java.util.TreeSet; +import java.util.Set; +import java.util.HashSet; +import java.util.Comparator; +import java.util.Iterator; + +import javax.swing.text.GapContent; +import javax.swing.text.PlainDocument; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; +import javax.swing.text.AttributeSet; +import javax.swing.text.View; + +import javax.swing.tree.DefaultMutableTreeNode; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; +import org.scilab.modules.console.utils.ScilabLaTeXViewer; + +/** + * The class ScilabDocument is used to render a document .sci or .sce + * @author Calixte DENIZET + */ +public class ScilabDocument extends PlainDocument implements DocumentListener { + + private static final long serialVersionUID = -1227880612912063687L; + + /** + * The EOL in mac OS + */ + public static final String EOLMAC = "\r"; + + /** + * The EOL in windows OS + */ + public static final String EOLWIN = "\r\n"; + + /** + * The EOL in unix OS + */ + public static final String EOLUNIX = "\n"; + + private static final int GAPBUFFERCAPACITY = 2; + private static final String LINE_SEPARATOR = "line.separator"; + private static final int INITFUNCTIONSNUMBER = 128; + + private View view; + private List<String> saved = new Vector<String>(); + private FunctionScanner funScanner; + + private Set<String> functions = new HashSet<String>(INITFUNCTIONSNUMBER); + + private boolean contentModified; + private boolean contentModifiedSinceBackup; + private boolean alphaOrder; + + // Editor's default encoding is UTF-8 + private String encoding; + private boolean updater = true; + private boolean binary; + private boolean autoIndent; + private boolean shouldMergeEdits; + private boolean undoManagerEnabled; + private CompoundUndoManager undo; + + private ScilabEditorPane pane; + private boolean focused; + + private String eolStyle; + + /** + * Constructor + */ + public ScilabDocument() { + this(true); + } + + /** + * Constructor + */ + public ScilabDocument(boolean paned) { + super(new GapContent(GAPBUFFERCAPACITY)); + contentModified = false; + + if (paned) { + setAsynchronousLoadPriority(2); + + autoIndent = SciNotesOptions.getSciNotesDisplay().automaticIndent; + encoding = Charset.forName(SciNotesOptions.getSciNotesPreferences().encoding).toString(); + eolStyle = SciNotesOptions.getSciNotesPreferences().eol; + + undo = new CompoundUndoManager(this); + addUndoableEditListener(undo); + undoManagerEnabled = true; + + contentModifiedSinceBackup = false; + } + } + + /** + * Set the ScilabEditorPane associated with this doc + * @param pane the ScilabEditorPane + */ + public void setEditorPane(ScilabEditorPane pane) { + this.pane = pane; + } + + /** + * Get the ScilabEditorPane associated with this doc + * @return pane the ScilabEditorPane + */ + public ScilabEditorPane getEditorPane() { + return pane; + } + + /** + * Set to true of the document is focused in the EditorPane + * @param b the boolean + */ + public void setFocused(boolean b) { + focused = b; + } + + /** + * Create a lexer used to colorize the text + * @return ScilabLexer the lexer + */ + public ScilabLexer createLexer(boolean update) { + return new ScilabLexer(this, update); + } + + /** + * Create a lexer used to colorize the text + * @param update true if the scilab vars must be updated + * @return ScilabLexer the lexer + */ + public ScilabLexer createLexer() { + return new ScilabLexer(this, true); + } + + /** + * @return the Set containing the functions name + */ + public Set<String> getFunctionsInDoc() { + return functions; + } + + /** + * Set the current view to render the code + * @param view the used view + */ + public void setView(View view) { + this.view = view; + } + + /** + * @return the current used view + */ + public View getView() { + return view; + } + + /** + * Get encoding + * @return String encoding + */ + public String getEncoding() { + return encoding; + } + + /** + * set Encoding + * @param encoding encoding + */ + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + /** + * Set to true if it's a binary doc + * @param binary boolean + */ + public void setBinary(boolean binary) { + this.binary = binary; + } + + /** + * @return true if it's a binary file + */ + public boolean getBinary() { + return binary; + } + + /** + * set end of line value + * @param eol String + */ + public void setEOL(String eol) { + this.eolStyle = eol; + } + + /** + * get end of line + * @return end of line + */ + public String getEOL() { + return this.eolStyle; + } + + /** + * get end of line + * @return end of line + */ + public String getDefaultEOL() { + return System.getProperty(LINE_SEPARATOR); + } + + /** + * isUpdater + * @return boolean + */ + public boolean isUpdater() { + return updater; + } + + /** + * getAutoIndent + * @return boolean + */ + public boolean getAutoIndent() { + return autoIndent; + } + + /** + * setAutoIndent + * @param b boolean + */ + public void setAutoIndent(boolean b) { + autoIndent = b; + } + + /** + * setUpdater + * @param updaterDisabled boolean + */ + public void setUpdater(boolean updaterDisabled) { + this.updater = updaterDisabled; + } + + /** + * Get document text + * @return String + */ + public String getText() { + try { + return getText(0, getLength()); + } catch (BadLocationException e) { + return ""; + } + } + + public void addEOL() { + if (SciNotesOptions.getSciNotesPreferences().addLineTermination) { + int len = getLength(); + if (getLength() >= 1) { + try { + String end = getText(len - 1, 1); + if (!end.equals("\n")) { + insertString(len, "\n", null); + } + } catch (BadLocationException e) { + System.err.println(e); + } + } else { + try { + insertString(len, "\n", null); + } catch (BadLocationException e) { + System.err.println(e); + } + } + } + } + + /** + * Begins a compound edit (for the undo) + */ + public void mergeEditsBegin() { + undo.endCompoundEdit(); + undo.startCompoundEdit(); + } + + /** + * Ends a compound edit (for the undo) + */ + public void mergeEditsEnd() { + undo.endCompoundEdit(); + } + + /** + * getUndoManager + * @return CompoundUndoManager + */ + public CompoundUndoManager getUndoManager() { + return undo; + } + + /** + * disableUndoManager + */ + public void disableUndoManager() { + if (undoManagerEnabled) { + this.removeUndoableEditListener(undo); + undoManagerEnabled = false; + } + } + + /** + * enableUndoManager + */ + public void enableUndoManager() { + if (!undoManagerEnabled) { + this.addUndoableEditListener(undo); + undoManagerEnabled = true; + } + } + + /** + * isContentModified + * @return boolean + */ + public boolean isContentModified() { + return contentModified; + } + + /** + * isContentModifiedSinceBackup + * @return boolean + */ + public boolean isContentModifiedSinceBackup() { + return contentModifiedSinceBackup; + } + + /** + * setContentModified + * @param contentModified boolean + */ + public void setContentModifiedSinceBackup(boolean contentModified) { + this.contentModifiedSinceBackup = contentModified; + } + + /** + * setContentModified + * @param contentModified boolean + */ + public void setContentModified(boolean contentModified) { + this.contentModified = contentModified; + if (pane != null && !contentModified) { + undo.setReference(); + pane.updateTitle(); + } else { + this.contentModifiedSinceBackup = true; + } + } + + /** + * dump document on stderr with line positions + */ + public void dump() { + readLock(); + try { + Element root = getDefaultRootElement(); + for (int i = 0; i != root.getElementCount(); ++i) { + Element e = root.getElement(i); + int start = e.getStartOffset(); + int end = e.getEndOffset(); + System.err.println("line " + i + " from: " + start + " to: " + end + ":|" + getText(start, end - start) + "|"); + } + } catch (BadLocationException e) { + System.err.println(e); + } + readUnlock(); + } + + /** + * Search the position of the function name in the Document + * @param name the name of the function + * @return the position where to go or -1 if not found + */ + public int searchFunctionByName(String name) { + Element root = getDefaultRootElement(); + for (int i = 0; i < root.getElementCount(); i++) { + Element e = root.getElement(i); + if (e instanceof ScilabLeafElement) { + ScilabLeafElement se = (ScilabLeafElement) e; + if (se.isFunction() && se.getFunctionInfo().functionName.equals(name)) { + return e.getStartOffset(); + } + } + } + return -1; + } + + /** + * @return a list containing all the infos about functions available in this document + */ + public List<FunctionScanner.FunctionInfo> getFunctionInfo() { + List<FunctionScanner.FunctionInfo> list = new ArrayList<FunctionScanner.FunctionInfo>(); + Element root = getDefaultRootElement(); + for (int i = 0; i < root.getElementCount(); i++) { + Element e = root.getElement(i); + if (e instanceof ScilabLeafElement) { + ScilabLeafElement se = (ScilabLeafElement) e; + if (se.isFunction()) { + list.add(se.getFunctionInfo()); + } + } + } + return list; + } + + /** + * @param alphaOrder is true if names must be sorted with alphabetic order + */ + public void setAlphaOrderInTree(boolean alphaOrder) { + this.alphaOrder = alphaOrder; + } + + /** + * Fill a tree with function's name according to alphabetic order or not + * @param base to fill + */ + public synchronized void fillTreeFuns(DefaultMutableTreeNode base) { + Element root = getDefaultRootElement(); + int nlines = root.getElementCount(); + if (!alphaOrder) { + for (int i = 0; i < nlines; i++) { + Element elem = root.getElement(i); + if (elem instanceof ScilabDocument.ScilabLeafElement) { + int type = ((ScilabDocument.ScilabLeafElement) elem).getType(); + switch (type) { + case ScilabDocument.ScilabLeafElement.NOTHING : + break; + case ScilabDocument.ScilabLeafElement.FUN : + base.add(new DefaultMutableTreeNode(elem)); + break; + case ScilabDocument.ScilabLeafElement.ENDFUN : + break; + default : + break; + } + } + } + } else { + Set<DefaultMutableTreeNode> set = new TreeSet<DefaultMutableTreeNode>(new Comparator<DefaultMutableTreeNode>() { + public int compare(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) { + ScilabLeafElement l1 = (ScilabLeafElement) o1.getUserObject(); + ScilabLeafElement l2 = (ScilabLeafElement) o2.getUserObject(); + int n = l1.getFunctionName().compareTo(l2.getFunctionName()); + if (n != 0) { + return n; + } + return l1.getStartOffset() - l2.getStartOffset(); + } + + public boolean equals(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) { + return false; + } + }); + for (int i = 0; i < nlines; i++) { + Element elem = root.getElement(i); + if (elem instanceof ScilabDocument.ScilabLeafElement) { + int type = ((ScilabDocument.ScilabLeafElement) elem).getType(); + switch (type) { + case ScilabDocument.ScilabLeafElement.NOTHING : + break; + case ScilabDocument.ScilabLeafElement.FUN : + set.add(new DefaultMutableTreeNode(elem)); + break; + case ScilabDocument.ScilabLeafElement.ENDFUN : + break; + default : + break; + } + } + } + Iterator<DefaultMutableTreeNode> iter = set.iterator(); + while (iter.hasNext()) { + base.add(iter.next()); + } + } + } + + /** + * Fill a tree with anchor's name according to alphabetic order or not + * @param base to fill + */ + public synchronized void fillTreeAnchors(DefaultMutableTreeNode base) { + Element root = getDefaultRootElement(); + int nlines = root.getElementCount(); + if (!alphaOrder) { + for (int i = 0; i < nlines; i++) { + ScilabLeafElement elem = (ScilabLeafElement) root.getElement(i); + if (elem.isAnchor()) { + base.add(new DefaultMutableTreeNode(elem)); + } + } + } else { + Set<DefaultMutableTreeNode> set = new TreeSet<DefaultMutableTreeNode>(new Comparator<DefaultMutableTreeNode>() { + public int compare(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) { + ScilabLeafElement l1 = (ScilabLeafElement) o1.getUserObject(); + ScilabLeafElement l2 = (ScilabLeafElement) o2.getUserObject(); + int n = l1.getAnchorName().compareTo(l2.getAnchorName()); + if (n != 0) { + return n; + } + return l1.getStartOffset() - l2.getStartOffset(); + } + + public boolean equals(DefaultMutableTreeNode o1, DefaultMutableTreeNode o2) { + return false; + } + }); + for (int i = 0; i < nlines; i++) { + ScilabLeafElement elem = (ScilabLeafElement) root.getElement(i); + if (elem.isAnchor()) { + set.add(new DefaultMutableTreeNode(elem)); + } + } + Iterator<DefaultMutableTreeNode> iter = set.iterator(); + while (iter.hasNext()) { + base.add(iter.next()); + } + } + } + + /** + * @return the first function name which appears in this doc or null + */ + public String getFirstFunctionName() { + Element root = getDefaultRootElement(); + for (int i = 0; i < root.getElementCount(); i++) { + Element e = root.getElement(i); + if (e instanceof ScilabLeafElement) { + ScilabLeafElement se = (ScilabLeafElement) e; + if (se.isFunction()) { + return se.getFunctionInfo().functionName; + } + } + } + return null; + } + + /** + * @param line the number of the line where to begin the search + * @return the next anchor + */ + public int nextAnchorFrom(int line) { + Element root = getDefaultRootElement(); + for (int i = line + 1; i < root.getElementCount(); i++) { + ScilabLeafElement se = (ScilabLeafElement) root.getElement(i); + if (se.isAnchor()) { + return i; + } + } + for (int i = 0; i < line; i++) { + ScilabLeafElement se = (ScilabLeafElement) root.getElement(i); + if (se.isAnchor()) { + return i; + } + } + + return -1; + } + + /** + * @param line the number of the line where to begin the search + * @return the previous anchor + */ + public int previousAnchorFrom(int line) { + Element root = getDefaultRootElement(); + for (int i = line - 1; i >= 0; i--) { + ScilabLeafElement se = (ScilabLeafElement) root.getElement(i); + if (se.isAnchor()) { + return i; + } + } + for (int i = root.getElementCount() - 1; i > line; i--) { + ScilabLeafElement se = (ScilabLeafElement) root.getElement(i); + if (se.isAnchor()) { + return i; + } + } + + return -1; + } + + /** + * Get the anchors between two positions + * @param start the beginning + * @param end the end + * @return a list of the anchors + */ + public List<Anchor> getAnchorsBetween(int start, int end) { + Element root = getDefaultRootElement(); + int lineS = root.getElementIndex(start); + int lineE = root.getElementIndex(end); + List<Anchor> list = new ArrayList<Anchor>(); + for (int i = lineS; i <= lineE; i++) { + final ScilabLeafElement se = (ScilabLeafElement) root.getElement(i); + if (se.isAnchor()) { + list.add(new Anchor(i, se.getAnchorName())); + } + } + + return list; + } + + /** + * Get the lhs/rhs args used in a function declaration + * @param pos the position in the document + * @return the two lists containing args and returned values or null if we are not + * in a function + */ + public List<String>[] getInOutArgs(int pos) { + Element root = getDefaultRootElement(); + int index = root.getElementIndex(pos); + int compt = 0; + while (index != -1) { + ScilabLeafElement e = (ScilabLeafElement) root.getElement(index--); + switch (e.getType()) { + case ScilabLeafElement.NOTHING : + break; + case ScilabLeafElement.FUN : + if (compt == 0) { + FunctionScanner.FunctionInfo info = e.getFunctionInfo(); + return new List[] {info.returnValues, info.argsValues}; + } else { + compt++; + } + break; + case ScilabLeafElement.ENDFUN : + compt--; + break; + default : + } + } + return null; + } + + /** + * Get the function name where the caret is + * @param pos the position in the document + * @return the nearest function name + */ + public String getCurrentFunction(int pos) { + Element root = getDefaultRootElement(); + int index = root.getElementIndex(pos); + int line = index; + int compt = 0; + while (index != -1) { + ScilabLeafElement e = (ScilabLeafElement) root.getElement(index--); + switch (e.getType()) { + case ScilabLeafElement.NOTHING : + break; + case ScilabLeafElement.FUN : + if (compt == 0) { + String str = e.getFunctionInfo().functionName; + if (str == null) { + str = SciNotesMessages.UNKNOWN_FUNCTION; + } + return String.format(SciNotesMessages.POSFUN_IN_DOC, line + 1, pos - root.getElement(line).getStartOffset(), str, line - index); + } else { + compt++; + } + break; + case ScilabLeafElement.ENDFUN : + compt--; + break; + default : + } + } + return String.format(SciNotesMessages.POS_IN_DOC, line + 1, pos - root.getElement(line).getStartOffset()); + } + + /** + * lock + */ + public void lock() { + super.writeLock(); + } + + /** + * unlock + */ + public void unlock() { + super.writeUnlock(); + } + + /** + * Nothing ! + * @param e the event + */ + public void changedUpdate(DocumentEvent e) { } + + /** + * Called when an insertion is made in the doc + * @param e the event + */ + public void insertUpdate(DocumentEvent e) { + handleEvent(e); + } + + /** + * Called when a remove is made in the doc + * @param e the event + */ + public void removeUpdate(DocumentEvent e) { + handleEvent(e); + } + + /** + * {@inheritDoc} + */ + protected void insertUpdate(DefaultDocumentEvent chng, AttributeSet attr) { + // Fix bug 8277 in putting attr=null + // Java, by default, highlights the chinese chars when entered on keyboard + super.insertUpdate(chng, null); + } + + /** + * @param ev the DocumentEvent to handle + */ + private void handleEvent(DocumentEvent ev) { + if (!contentModified) { + contentModified = true; + if (pane != null) { + pane.updateTitle(); + } + } + + contentModifiedSinceBackup = true; + + DocumentEvent.ElementChange chg = ev.getChange(getDefaultRootElement()); + if (chg != null) { + Element[] added = chg.getChildrenAdded(); + Element[] removed = chg.getChildrenRemoved(); + if ((added != null && added.length > 0) || (removed != null && removed.length > 0)) { + for (int i = 0; i < removed.length; i++) { + String name = ((ScilabLeafElement) removed[i]).getFunctionName(); + if (name != null && name.length() != 0) { + functions.remove(name); + } + } + for (int i = 0; i < added.length; i++) { + ((ScilabLeafElement) added[i]).resetType(); + ((ScilabLeafElement) added[i]).resetTypeWhenBroken(); + String name = ((ScilabLeafElement) added[i]).getFunctionName(); + if (name != null && name.length() != 0) { + functions.add(name); + } + } + } + } else { + // change occurred only on one line + Element root = getDefaultRootElement(); + int index = root.getElementIndex(ev.getOffset()); + ScilabLeafElement line = (ScilabLeafElement) root.getElement(index); + boolean broken = line.isBroken(); + if (pane != null && (line.resetType() == ScilabLeafElement.FUN || broken != line.isBroken() + || (index > 0 && ((ScilabLeafElement) root.getElement(index - 1)).isBroken()))) { + pane.repaint(); + } + } + + if (pane != null) { + KeywordEvent e = pane.getKeywordEvent(); + + if (ScilabLexerConstants.isLaTeX(e.getType())) { + try { + int start = e.getStart(); + int end = start + e.getLength(); + String exp = getText(start, e.getLength()); + int height = pane.getScrollPane().getHeight() + pane.getScrollPane().getVerticalScrollBar().getValue(); + ScilabLaTeXViewer.displayExpressionIfVisible(pane, height, exp, start, end); + } catch (BadLocationException ex) { } + } + } + } + + /** + * @overload #createDefaultRoot + * @return the element base + */ + protected AbstractElement createDefaultRoot() { + funScanner = new FunctionScanner(this); + BranchElement map = (BranchElement) createBranchElement(null, null); + Element line = createLeafElement(map, null, 0, 1); + map.replace(0, 0, new Element[] {line}); + return map; + } + + /** + * @overload #createLeafElement + * @param parent the parent Element + * @param a an AttributeSet + * @param p0 start in the doc + * @param p1 end in the doc + * @return the created LeafElement + */ + protected Element createLeafElement(Element parent, AttributeSet a, int p0, int p1) { + return new ScilabLeafElement(parent, a, p0, p1); + } + + /** + * Inner class to consider the type of a line : + * - FUN : function y=foo(x) + * - ENDFUN : endfunction + * - NOTHING : bla bla bla + * This inner class is useful to make a line numbering compatible with the whereami macro. + */ + public class ScilabLeafElement extends LeafElement { + + private static final long serialVersionUID = 4389590345677765643L; + + /** + * Nothing in this line + */ + public static final int NOTHING = 0; + + /** + * function ... in this line + */ + public static final int FUN = 1; + + /** + * endfunction in this line + */ + public static final int ENDFUN = 2; + + /** + * broken line + */ + public static final int BROKEN = 4; + + private boolean visible = true; + private int previousType; + private int type; + private FunctionScanner.FunctionInfo info; + private boolean broken; + private boolean brokenString; + + private boolean anchor; + private String anchorName; + + /** + * The same constructor as in LeafElement. + * @param parent the parent Element + * @param a an AttributeSet + * @param p0 start in the doc + * @param p1 end in the doc + */ + public ScilabLeafElement(Element parent, AttributeSet a, int p0, int p1) { + super(parent, a, p0, p1); + type = funScanner.getLineType(p0, p1); + if ((type & BROKEN) == BROKEN) { + broken = true; + type -= BROKEN; + } + + if (type == FUN) { + info = funScanner.getFunctionInfo(); + } + } + + /** + * Reset type (normally called on a change in the document) + * @return the new type + */ + public int resetType() { + String oldName = ""; + if (type == FUN) { + oldName = info.functionName; + } + + previousType = type; + type = funScanner.getLineType(getStartOffset(), getEndOffset()); + + if ((type & BROKEN) == BROKEN) { + broken = true; + type -= BROKEN; + } else { + broken = false; + } + + if (type == FUN) { + info = funScanner.getFunctionInfo(); + if (info.functionName != null) { + if (!info.functionName.equals(oldName)) { + functions.remove(oldName); + functions.add(info.functionName); + } + } else { + functions.remove(oldName); + } + } + + resetTypeWhenBroken(); + + return type; + } + + /** + * @return true if the Line number panel need to be refreshed (useful in whereami mode) + */ + public boolean needLineNumberRepaint() { + return type == FUN || type == ENDFUN || type != previousType; + } + + /** + * If the previous line is broken, then this line is a part of it + * so we need to resetType of the previous. + */ + public void resetTypeWhenBroken() { + int p0 = getStartOffset(); + if (p0 != 0) { + Element parent = getParentElement(); + ScilabLeafElement elem = (ScilabLeafElement) parent.getElement(parent.getElementIndex(p0 - 1)); + if (elem.broken) { + elem.resetType(); + } + } + } + + /** + * @return the type of this line (FUN,...) + */ + public int getType() { + return type; + } + + /** + * @return the info about this line containing a function def + */ + public FunctionScanner.FunctionInfo getFunctionInfo() { + return info; + } + + /** + * @return if this line begins with function + */ + public boolean isFunction() { + return type == FUN; + } + + /** + * @return if this line begins with endfunction + */ + public boolean isEndfunction() { + return type == ENDFUN; + } + + /** + * @return if this line is visible + */ + public boolean isVisible() { + return visible; + } + + /** + * @param b true if this line is visible + */ + public void setVisible(boolean b) { + visible = b; + } + + /** + * @return if this line is broken + */ + public boolean isBroken() { + return broken; + } + + /** + * @param b true if this line is broken + */ + public void setBroken(boolean b) { + broken = b; + } + + /** + * @return if this line is broken + */ + public boolean isBrokenString() { + return brokenString; + } + + /** + * @param b true if this line is broken in a string + */ + public void setBrokenString(boolean b) { + brokenString = b; + if (b) { + broken = true; + } + } + + /** + * @return the function's name + */ + public String getFunctionName() { + if (type == FUN) { + return info.functionName; + } + return ""; + } + + /** + * @return if this line is an anchor + */ + public boolean isAnchor() { + return anchor; + } + + /** + * @param name the name of the anchor, if null remove + * the anchor. + */ + public void setAnchor(String name) { + if (name == null) { + anchor = false; + return; + } + + anchor = true; + anchorName = name; + } + + /** + * @return the name of the anchor if exists + */ + public String getAnchorName() { + if (anchor) { + return anchorName; + } else { + return ""; + } + } + + /** + * @return String representation + */ + public String toString() { + if (anchor) { + if (type == FUN) { + return "function: " + info.functionName + " & anchor: " + anchorName; + } else { + return anchorName; + } + } + return info.functionName; + } + } + + /** + * Inner class to get infos on anchor + */ + public class Anchor { + + private int line; + private String name; + + /** + * Default constructor + * @param line the line where the anchor is + * @param name the anchor's name + */ + public Anchor(int line, String name) { + this.line = line; + this.name = name; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return name; + } + + /** + * @return the line number + */ + public int getLine() { + return line; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabDocumentReader.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabDocumentReader.java new file mode 100755 index 000000000..312896cba --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabDocumentReader.java @@ -0,0 +1,122 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.io.Reader; +import java.io.IOException; +import javax.swing.text.BadLocationException; +import javax.swing.text.Segment; + +/** + * Class ScilabDocumentReader provides a read method to read a part of the document + * from left to right and from right to left (useful to find matching keywords such + * as function...endfunction or noitcnufdne...noitcnuf) + * @author Calixte DENIZET + */ +public class ScilabDocumentReader extends Reader { + + private static final String BADLOCATION = "Bad Location in document"; + + private int end; + private int pos; + private boolean fromEnd; + private ScilabDocument doc; + private Segment segment; + + /** + * Constructor for a reader from left to right + * @param doc the doc to read + * @param start the start in the doc + * @param end the end in the doc + */ + public ScilabDocumentReader(ScilabDocument doc, int start, int end) { + this(doc, false, start, end); + } + + /** + * Constructor for a reader from left to right (fromEnd == false) or from right to left (fromEnd == true). + * @param doc the doc to read + * @param fromEnd LR or RL + * @param start the start in the doc + * @param end the end in the doc + */ + public ScilabDocumentReader(ScilabDocument doc, boolean fromEnd, int start, int end) { + this.doc = doc; + this.segment = new Segment(); + if (fromEnd) { + this.pos = Math.min(start, doc.getLength()); + this.end = end; + } else { + this.pos = start; + this.end = Math.min(end, doc.getLength()); + } + this.fromEnd = fromEnd; + } + + /** + * The read method for a Reader. + * @param cbuf the buffer where to put the chars + * @param pos position in the doc + * @param len the number of chars to be read + * @return the number of read chars + * @throws IOException if a problem is encountered + */ + public int read(char[] cbuf, int pos, int len) throws IOException { + if (doc == null) { + throw new IOException("Reader closed"); + } + int length = len; + + if (!fromEnd) { + if (this.pos < end) { + if (length > end - this.pos) { + length = end - this.pos; + } + try { + doc.getText(this.pos, length, segment); + System.arraycopy(segment.array, segment.offset, cbuf, pos, length); + this.pos += length; + return length; + } catch (BadLocationException e) { + throw new IOException(BADLOCATION); + } + } + } else { + if (this.pos > end) { + if (length > this.pos - end + 1) { + length = this.pos - end + 1; + } + try { + doc.getText(this.pos - length + 1, length, segment); + int ppos = segment.offset + segment.count - 1; + for (int i = 0; i < length; i++) { + cbuf[pos + i] = segment.array[ppos - i]; + } + this.pos -= length; + return length; + } catch (BadLocationException e) { + throw new IOException(BADLOCATION); + } + } + } + return -1; + } + + /** + * The close method of a Reader + * @throws IOException if a problem is encountered + */ + public void close() throws IOException { + doc = null; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabEditorKit.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabEditorKit.java new file mode 100755 index 000000000..110345dcd --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabEditorKit.java @@ -0,0 +1,302 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.CharBuffer; +import java.nio.charset.CharacterCodingException; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.charset.CodingErrorAction; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Document; +import javax.swing.text.ViewFactory; + +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.actions.EncodingAction; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * The class ScilabEditorKit provides the minimal things needed to render + * a Scilab's document. + * @author Calixte DENIZET + */ +public class ScilabEditorKit extends DefaultEditorKit { + + private static final long serialVersionUID = 8005575461386086815L; + + /** + * The mimetype for a scilab code + */ + public static final String MIMETYPE = "text/scilab"; + private static final int BUFFERCAPACITY = 8192; + public static final String[] ENCODINGS = new String[] {"utf-8", "windows-1252", "iso-8859-1"}; + private static final Map<String, Integer> encPos = new HashMap<String, Integer>(ENCODINGS.length); + + static { + for (int i = 0; i < ENCODINGS.length; i++) { + encPos.put(ENCODINGS[i], i); + } + } + + private final char[] buffer = new char[BUFFERCAPACITY]; + + private ScilabContext preferences; + private boolean plain; + + /** + * Default constructor + */ + public ScilabEditorKit() { + super(); + } + + /** + * Constructor + * @param plain is true to use a plain view (no line-wrapping) + */ + public ScilabEditorKit(boolean plain) { + super(); + this.plain = plain; + } + + public boolean isPlain() { + return plain; + } + + /** + * @return the mime type + */ + public String getContentType() { + return MIMETYPE; + } + + /** + * @return a new ScilabDocument + */ + public Document createDefaultDocument() { + return new ScilabDocument(); + } + + /** + * @return the context associated with the ScilabDocument + */ + public ScilabContext getStylePreferences() { + if (preferences == null) { + preferences = new ScilabContext(plain); + } + + return preferences; + } + + /** + * Set the context to render the document + * @param prefs the context to use + */ + public void setStylePreferences(ScilabContext prefs) { + preferences = prefs; + } + + /** + * @return the ViewFactory used to create a View to render a ScilabDocument + */ + public ViewFactory getViewFactory() { + return getStylePreferences(); + } + + /** + * @param file the file to test + * @return the corresponding charset if exists + * @throws IOExecption if I/O problems are met + * @throws CharacterCodingException if no charset is found + */ + public static Charset tryToGuessEncoding(File file) throws IOException, CharacterCodingException { + for (int i = 0; i < ENCODINGS.length; i++) { + if (tryToGuessEncoding(file, Charset.forName(ENCODINGS[i]))) { + return Charset.forName(ENCODINGS[i]); + } + } + + throw new CharacterCodingException(); + } + + /** + * @param file the file to test + * @param charset the charset to test + * @return true if the file can be decoded with the charset + * @throws IOExecption if I/O problems are met + */ + public static boolean tryToGuessEncoding(File file, Charset charset) throws IOException { + char[] cbuf = new char[BUFFERCAPACITY]; + CharsetDecoder decoder = charset.newDecoder().onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT); + FileInputStream fis = new FileInputStream(file); + InputStreamReader inReader = new InputStreamReader(fis, decoder); + BufferedReader bufReader = new BufferedReader(inReader); + try { + while (bufReader.read(cbuf) != -1) { + ; + } + fis.close(); + inReader.close(); + bufReader.close(); + return true; + } catch (Exception e) { } + + return false; + } + + /** + * The read method is used to read the file and to write its contents + * in the document at position pos + * @param file the file to read + * @param doc the Document where to write + * @param pos position where to write + * @throws CharacterCodingException if an unreadable char is encountered + * @throws IOException if a problem is encountered in reading the stream + * @throws BadLocationException if the pos is invalid + */ + public void read(SciNotes editor, File file, Document doc, int pos) throws IOException, BadLocationException { + Charset charset = Charset.forName(SciNotesOptions.getSciNotesPreferences().encoding); + try { + charset = tryToGuessEncoding(file); + } catch (CharacterCodingException e) { + ScilabModalDialog.show(editor, SciNotesMessages.CANNOT_GUESS_ENCODING, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + ((ScilabDocument) doc).setEncoding(charset.toString()); + EncodingAction.updateEncodingMenu((ScilabDocument) doc); + FileInputStream fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis, charset); + BufferedReader br = new BufferedReader(isr); + read(br, doc, pos); + try { + br.close(); + } catch (IOException e) { } + } + + /** + * The read method is used to read the Reader and to write its contents + * in the document at position pos + * @param in the Reader to read + * @param doc the Document where to write + * @param pos position where to write + * @throws IOException if a problem is encountered in reading the stream + * @throws BadLocationException if the pos is invalid + */ + public void read(Reader in, Document doc, int pos) throws IOException, BadLocationException { + DocString docString = read(in); + ((ScilabDocument) doc).setEOL(docString.eol); + ((ScilabDocument) doc).setBinary(docString.isBinary); + doc.insertString(pos, docString.content, null); + } + + /** + * The read method is used to read the Reader and to write its contents + * in the document at position pos + * @param in the Reader to read + * @throws IOException if a problem is encountered in reading the stream + */ + public DocString read(Reader in) throws IOException { + int nch; + int i; + int prev; + int inc = 0; + boolean win = false; + boolean mac = false; + boolean first = true; + boolean binary = false; + DocString docString = new DocString(); + StringBuilder sbuf = new StringBuilder(buffer.length); + while ((nch = in.read(buffer, 0, buffer.length)) != -1) { + if (first) { + /* We try to know if we have a binary file + The rule is : two \0 in the first 8ko : it's binary ! */ + CharBuffer cb = CharBuffer.wrap(buffer); + byte[] bytes = Charset.forName("utf-8").encode(cb).array(); + for (i = 0; i < nch; i++) { + if (bytes[i] == 0 ) { + inc++; + if (inc == 2) { + binary = true; + break; + } + } + } + first = false; + } + + prev = 0; + if (!binary) { + for (i = 0; i < nch - 1; i++) { + if (buffer[i] == '\r') { + buffer[i] = '\n'; + sbuf.append(buffer, prev, i - prev + 1); + if (buffer[i + 1] == '\n') { + i++; + if (!win && !mac) { + docString.eol = ScilabDocument.EOLWIN; + win = true; + } + } else { + if (!win && !mac) { + docString.eol = ScilabDocument.EOLMAC; + mac = true; + } + } + + prev = i + 1; + } + } + + if (i == nch - 1) { + if (buffer[i] == '\r') { + if (!win && !mac) { + docString.eol = ScilabDocument.EOLMAC; + } + buffer[i] = '\n'; + } + sbuf.append(buffer, prev, i - prev + 1); + } + } else { + sbuf.append(buffer, 0, nch); + } + } + if (!win && !mac) { + docString.eol = ScilabDocument.EOLUNIX; + } + + docString.isBinary = inc == 2; + docString.content = sbuf.toString(); + + return docString; + } + + public static class DocString { + + public String eol; + public boolean isBinary; + public String content; + + DocString() { } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabEditorPane.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabEditorPane.java new file mode 100755 index 000000000..44ca5dfd2 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabEditorPane.java @@ -0,0 +1,1758 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.io.File; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JEditorPane; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIManager; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.EventListenerList; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; +import javax.swing.text.View; + +import org.scilab.modules.commons.OS; +import org.scilab.modules.commons.gui.ScilabCaret; +import org.scilab.modules.console.utils.ScilabLaTeXViewer; +import org.scilab.modules.gui.messagebox.MessageBox; +import org.scilab.modules.gui.messagebox.ScilabMessageBox; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.gui.utils.WebBrowser; +import org.scilab.modules.scinotes.actions.CopyAsHTMLAction; +import org.scilab.modules.scinotes.actions.OpenSourceFileOnKeywordAction; +import org.scilab.modules.scinotes.utils.NavigatorWindow; +import org.scilab.modules.scinotes.utils.ScilabScrollPane; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * Class ScilabEditorPane + * @author Calixte DENIZET + * + */ +public class ScilabEditorPane extends JEditorPane implements Highlighter.HighlightPainter, + CaretListener, MouseListener, + MouseMotionListener, Cloneable, + KeyListener { + + private static final long serialVersionUID = 4322071415211939097L; + + private static final String TIRET = " - "; + private static final Cursor HANDCURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); + private static final Cursor TEXTCURSOR = Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR); + private static final DefaultHighlighter.DefaultHighlightPainter HIGHLIGHTER = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW); + + private static ScilabEditorPane focused; + + private Color highlightColor; + private Color highlightContourColor; + private boolean highlightEnable; + private Object highlightCL; + private boolean matchingKeywordsEnable; + private boolean matchingOpenersEnable; + private boolean overwriteMode; + private ScilabLexer lexer; + private SciNotes editor; + private IndentManager indent; + private TabManager tab; + private CommentManager com; + private HelpOnTypingManager helpOnTyping; + private TrailingWhiteManager trailingWhite; + private boolean readonly; + private boolean binary; + private String infoBar = ""; + private String shortName = ""; + private String title = ""; + + private Timer selectionTimer; + private Timer matcherTimer; + + private Point mousePoint; + + private long lastModified; + private long lastExternalModification; + + /* matchLR matches Left to Right ... */ + private MatchingBlockManager matchLR; + private MatchingBlockManager matchRL; + + private boolean suppressCom = true; + + private SciNotesLineNumberPanel xln; + private ScilabEditorPane rightTextPane; + private UUID uuid; + + private EditorComponent edComponent; + + private boolean hand; + private boolean infoBarChanged; + private boolean ctrlHit; + + private Color saveHighlightContourColor; + private Color saveHighlightColor; + private boolean hasBeenSaved; + private boolean saveHighlightEnable; + + private EventListenerList kwListeners = new EventListenerList(); + private Map<Integer, Object> highlightedWords = new HashMap<Integer, Object>(); + + //private List<Object> highlightedWords = new ArrayList<Object>(); + //private List<Integer> highlightedWordsBegin = new ArrayList<Integer>(); + + /** + * Constructor + * @param editor which uses this pane + */ + public ScilabEditorPane(SciNotes editor) { + super(); + if (focused == null) { + focused = this; + } + this.editor = editor; + this.uuid = UUID.randomUUID(); + edComponent = new EditorComponent(this); + + /* + When SciNotes is docked and has two tabs, switching the tabs causes a focus loss. + The focus is gave to the other docked component and that generates a toolbar change. + The solution is to set FocusCycleRoot to false (set to true by default in JEditorPane). + */ + setFocusCycleRoot(false); + + addCaretListener(this); + addMouseMotionListener(this); + addMouseListener(this); + enableMatchingKeywords(SciNotesOptions.getSciNotesDisplay().highlightKeywords); + enableMatchingOpeners(SciNotesOptions.getSciNotesDisplay().highlightBrackets); + setFocusable(true); + addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + updateInfosWhenFocused(); + if (ScilabEditorPane.this.editor != null) { + NavigatorWindow nav = ScilabEditorPane.this.editor.getNavigator(); + if (nav != null) { + nav.update((ScilabDocument) getDocument()); + } + } + setMustAdjustVisibility(true); + } + + public void focusLost(FocusEvent e) { + ((ScilabDocument) getDocument()).setFocused(false); + if (e.getOppositeComponent() == getOtherPaneInSplit()) { + setMustAdjustVisibility(false); + } + } + }); + + addKeywordListener(new KeywordAdapter.MouseOverAdapter() { + public void caughtKeyword(KeywordEvent e) { + if (ScilabLexerConstants.isClickable(e.getType())) { + if (ctrlHit) { + setCursor(HANDCURSOR); + hand = true; + try { + String url = ((ScilabDocument) getDocument()).getText(e.getStart(), e.getLength()); + if (ScilabLexerConstants.isClickable(e.getType())) { + String text; + switch (e.getType()) { + case ScilabLexerConstants.URL : + text = SciNotesMessages.OPENURL; + break; + case ScilabLexerConstants.MAIL : + text = SciNotesMessages.MAILTO; + break; + case ScilabLexerConstants.MACROS : + text = SciNotesMessages.OPENSOURCE; + break; + case ScilabLexerConstants.MACROINFILE : + text = SciNotesMessages.SHOWSOURCE; + break; + default : + text = null; + } + + if (text != null && ScilabEditorPane.this.editor != null) { + ScilabEditorPane.this.editor.getInfoBar().setText(text + url); + infoBarChanged = true; + } + } + } catch (BadLocationException ex) { } + } else if (ScilabEditorPane.this.editor != null) { + ScilabEditorPane.this.editor.getInfoBar().setText(SciNotesMessages.CLICKABLE_URL); + infoBarChanged = true; + if (hand) { + setCursor(TEXTCURSOR); + hand = false; + } + } + } else { + if (hand) { + setCursor(TEXTCURSOR); + hand = false; + } + if (infoBarChanged && ScilabEditorPane.this.editor != null) { + ScilabEditorPane.this.editor.getInfoBar().setText(infoBar); + infoBarChanged = false; + } + if (ScilabLexerConstants.isLaTeX(e.getType())) { + try { + int start = e.getStart(); + int end = start + e.getLength(); + String exp = ((ScilabDocument) getDocument()).getText(start, e.getLength()); + ScilabScrollPane ssp = getScrollPane(); + int height; + if (ssp != null) { + height = ssp.getHeight() + ssp.getVerticalScrollBar().getValue(); + } else { + height = edComponent.getHeight(); + } + ScilabLaTeXViewer.displayExpression(ScilabEditorPane.this, height, exp, start, end); + } catch (BadLocationException ex) { } + } else { + ScilabLaTeXViewer.removeLaTeXViewer(ScilabEditorPane.this); + } + } + } + }); + + addKeywordListener(new KeywordAdapter.MouseClickedAdapter() { + public void caughtKeyword(KeywordEvent e) { + if (ctrlHit && ScilabLexerConstants.isClickable(e.getType())) { + try { + hand = false; + ctrlHit = false; + infoBarChanged = false; + setCursor(TEXTCURSOR); + if (ScilabEditorPane.this.editor != null) { + ScilabEditorPane.this.editor.getInfoBar().setText(infoBar); + } + String url = ((ScilabDocument) getDocument()).getText(e.getStart(), e.getLength()); + if (ScilabLexerConstants.URL == e.getType() || ScilabLexerConstants.MAIL == e.getType()) { + WebBrowser.openUrl(url); + } else if (ScilabLexerConstants.isOpenable(e.getType())) { + OpenSourceFileOnKeywordAction.openSource(ScilabEditorPane.this, url); + } + } catch (BadLocationException ex) { } + } + } + }); + + getScrollPane().addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + if ((OS.get() == OS.MAC && e.isMetaDown()) || e.isControlDown()) { + int n = e.getWheelRotation(); + SciNotes.updateFontSize(n); + e.consume(); + } + } + }); + + addKeyListener(this); + setTransferHandler(new CopyAsHTMLAction.HTMLTransferHandler()); + + ((ScilabCaret) getCaret()).setMustAdjustVisibility(false); + } + + public void enableColorization(boolean b) { + View view = ((ScilabDocument) getDocument()).getView(); + if (view != null) { + if (view instanceof ScilabView) { + ((ScilabView) view).enable(b); + } else { + ((ScilabPlainView) view).enable(b); + } + } + } + + public void configurationChanged(SciNotesConfiguration.Conf conf) { + ((ScilabEditorKit) getEditorKit()).getStylePreferences().configurationChanged(conf); + + if (conf.font) { + resetFont(); + } + + if (conf.display) { + enableHighlightedLine(SciNotesOptions.getSciNotesDisplay().highlightCurrentLine); + setHighlightedLineColor(SciNotesOptions.getSciNotesDisplay().currentLineColor); + enableColorization(SciNotesOptions.getSciNotesDisplay().keywordsColorization); + setBackground(SciNotesOptions.getSciNotesDisplay().backgroundColor); + setCaretColor(SciNotesOptions.getSciNotesDisplay().caretColor); + + boolean kw = SciNotesOptions.getSciNotesDisplay().highlightKeywords; + boolean op = SciNotesOptions.getSciNotesDisplay().highlightBrackets; + + if ((kw || op) && (!matchingKeywordsEnable && !matchingOpenersEnable)) { + matchLR = new MatchingBlockManager((ScilabDocument) getDocument(), this, true, getHighlighter()); + matchLR.setDefaults(); + matchRL = new MatchingBlockManager((ScilabDocument) getDocument(), this, false, getHighlighter()); + matchRL.setDefaults(); + enableMatchingKeywords(kw); + enableMatchingOpeners(op); + return; + } + + if ((kw || op) && (matchingKeywordsEnable || matchingOpenersEnable)) { + matchLR.configurationChanged(conf); + matchRL.configurationChanged(conf); + return; + } + + if ((!kw && !op) && (matchingKeywordsEnable || matchingOpenersEnable)) { + matchLR.desactivateMouseOver(); + matchLR = null; + matchRL.desactivateMouseOver(); + matchRL = null; + return; + } + } + } + + /** + * @return the lexer + */ + public ScilabLexer getLexer() { + return lexer; + } + + /** + * {@inheritDoc} + * When no split and in wrapped view , this method return true and the consequence is + * that there is no horizontal scrollbar. + */ + public boolean getScrollableTracksViewportWidth() { + if (((ScilabDocument) getDocument()).getView() instanceof ScilabView) { + return !edComponent.isSplited(); + } else { + return super.getScrollableTracksViewportWidth(); + } + } + + /** + * @return true if the pane is in OverWrite mode (insert) + */ + public boolean getOverwriteMode() { + return this.overwriteMode; + } + + /** + * @param overwriteMode true if the pane is in OverWrite mode (insert) + */ + public void setOverwriteMode(boolean overwriteMode) { + this.overwriteMode = overwriteMode; + ((ScilabCaret) getCaret()).setOverwriteMode(overwriteMode); + } + + /** + * {@inheritDoc} + */ + public void replaceSelection(String content) { + if (overwriteMode && getSelectionStart() == getSelectionEnd()) { + int pos = getCaretPosition(); + select(pos, pos + content.length()); + } + + if (((SciNotesCaret) getCaret()).isEmptySelection()) { + super.replaceSelection(content); + } else { + SciNotesCaret caret = (SciNotesCaret) getCaret(); + int[][] pos = caret.getSelectedPositions(); + List<Object> sels = caret.getSelections(); + int len = content.length(); + int res = 0; + int sres; + ScilabDocument doc = (ScilabDocument) getDocument(); + doc.getUndoManager().enableOneShot(true); + doc.mergeEditsBegin(); + caret.protectHighlights(true); + for (int i = 0; i < pos.length; i++) { + if (sels.get(i) != null) { + sres = pos[i][0] + res; + try { + doc.replace(sres, pos[i][1] - pos[i][0], content, null); + } catch (BadLocationException e) { } + res = sres + len - pos[i][1]; + pos[i][0] = sres + len; + pos[i][1] = sres + len; + } + } + doc.mergeEditsEnd(); + doc.getUndoManager().enableOneShot(false); + caret.protectHighlights(false); + caret.updateHighlights(); + } + } + + /** + * Nothing ! + * @param e the event + */ + public void keyPressed(KeyEvent e) { + // Workaround for bug 7238 + if (e.getKeyLocation() == KeyEvent.KEY_LOCATION_NUMPAD + && e.getKeyCode() == KeyEvent.VK_DELETE + && e.getKeyChar() != KeyEvent.VK_DELETE) { + e.setKeyCode(KeyEvent.VK_DECIMAL); + ctrlHit = false; + } else if (mousePoint != null && e.getKeyCode() == KeyEvent.VK_CONTROL) { + ctrlHit = true; + preventConcernedKeywordListener(viewToModel(mousePoint), e, KeywordListener.ONMOUSEOVER); + } else { + ctrlHit = false; + } + } + + /** + * Nothing ! + * @param e the event + */ + public void keyReleased(KeyEvent e) { + if (mousePoint != null && e.getKeyCode() == KeyEvent.VK_CONTROL) { + ctrlHit = false; + preventConcernedKeywordListener(viewToModel(mousePoint), e, KeywordListener.ONMOUSEOVER); + } + } + + /** + * Nothing ! + * @param e the event + */ + public void keyTyped(KeyEvent e) { } + + /** + * @overload #setDocument + * @param doc to set + */ + public void setDocument(Document doc) { + super.setDocument(doc); + if (doc instanceof ScilabDocument) { + ((ScilabDocument) doc).getUndoManager().discardAllEdits(); + initialize((ScilabDocument) doc); + } + } + + /** + * {@inheritDoc} + */ + public void setName(String name) { + setNameInSuper(name); + setShortNameAndTitle(name); + ScilabEditorPane pane = getOtherPaneInSplit(); + if (pane != null) { + // I don't call pane.setName since we will enter in an infinite loop + pane.setNameInSuper(name); + pane.setShortNameAndTitle(name); + } + } + + /** + * @param name the name + */ + private void setNameInSuper(String name) { + super.setName(name); + } + + /** + * @param name the name + */ + private void setShortNameAndTitle(String name) { + if (name != null) { + File f = new File(name); + setShortName(f.getName()); + title = shortName + " (" + f.getAbsolutePath() + ")" + TIRET + SciNotesMessages.SCILAB_EDITOR; + } + } + + /** + * @param title the title + */ + public void setTitle(String title) { + this.title = title + TIRET + SciNotesMessages.SCILAB_EDITOR; + } + + /** + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * @param name the short name + */ + public void setShortName(String name) { + this.shortName = name; + } + + /** + * @return the short name of the file (without the full path) + */ + public String getShortName() { + return shortName; + } + + /** + * Init the pane + */ + public void init(final int pos) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + requestFocus(); + if (getCaret() != null) { + setCaretPosition(pos); + } + } + }); + } + + /** + * Close this pane + */ + public void close() { + FocusListener[] l = getFocusListeners(); + for (int i = 0; i < l.length; i++) { + removeFocusListener(l[i]); + } + if (getCaret() instanceof SciNotesCaret) { + ((SciNotesCaret) getCaret()).clean(); + super.setCaret(null); + if (selectionTimer != null && selectionTimer.isRunning()) { + selectionTimer.stop(); + selectionTimer = null; + } + if (matcherTimer != null && matcherTimer.isRunning()) { + matcherTimer.stop(); + matcherTimer = null; + } + } + } + + /** + * Update infos + */ + public void updateInfosWhenFocused() { + ScilabDocument doc = (ScilabDocument) getDocument(); + doc.setFocused(true); + SciNotes.setEditor(editor); + focused = this; + doc.getUndoManager().enableUndoRedoButtons(); + + if (editor != null) { + if (checkExternalModif() && lastExternalModification < getLastModification()) { + editor.getInfoBar().setText(SciNotesMessages.EXTERNAL_MODIFICATION_INFO); + if (ScilabModalDialog.show(editor, String.format(SciNotesMessages.ASK_TO_RELOAD, getShortName()), SciNotesMessages.RELOAD, IconType.QUESTION_ICON, ButtonType.YES_NO) == AnswerOption.YES_OPTION) { + editor.reload(getEditor().getTabPane().indexOfComponent(getEditorComponent())); + editor.getTextPane().updateInfosWhenFocused(); + } + lastExternalModification = getLastModification(); + } else { + editor.getInfoBar().setText(getInfoBarText()); + } + } + } + + /** + * @return true if an external modif occurred + */ + public boolean checkExternalModif() { + String path = getName(); + if (path != null) { + File f = new File(path); + if (f != null && f.exists()) { + return lastModified < f.lastModified(); + } else { + return true; + } + } + return false; + } + + /** + * Get last modification on file + * @return the lastModified value + */ + public long getLastModification() { + String path = getName(); + if (path != null) { + File f = new File(path); + if (f != null && f.exists()) { + return f.lastModified(); + } + } + + return -1; + } + + /** + * @return the String which must be displayed in the infobar + */ + public String getInfoBarText() { + return infoBar; + } + + /** + * @param text String which must be displayed in the infobar + */ + public void setInfoBarText(String text) { + this.infoBar = text; + if (editor != null) { + editor.getInfoBar().setText(getInfoBarText()); + } + } + + /** + * @param readonly true to set Read-Only mode + */ + public void setReadOnly(boolean readonly) { + this.readonly = readonly; + setEditable(!readonly); + setDragEnabled(!readonly); + if (readonly) { + infoBar = SciNotesMessages.READ_ONLY_MODE; + } else { + infoBar = ""; + } + } + + /** + * @param binary true to set binary mode + */ + public void setBinary(boolean binary) { + this.binary = binary; + setEditable(!binary); + setDragEnabled(!binary); + if (binary) { + infoBar = SciNotesMessages.BINARY_FILE_MODE; + disableAll(); + } else { + infoBar = ""; + } + } + + /** + * Copy the props of this textPane to pane + * @param pane the pane which receives the same props as this + */ + public void copyProps(ScilabEditorPane pane) { + pane.lastModified = lastModified; + pane.highlightEnable = highlightEnable; + pane.matchingKeywordsEnable = matchingKeywordsEnable; + pane.matchingOpenersEnable = matchingOpenersEnable; + pane.suppressCom = suppressCom; + pane.setName(getName()); + pane.setShortName(getShortName()); + pane.setTitle(getTitle().substring(0, getTitle().lastIndexOf(TIRET))); + pane.setEditable(isEditable()); + } + + /** + * Get the UUID associated with the editor pane instance. + * @return unique identifier + */ + public UUID getUUID() { + return uuid; + } + + /** + * Get the time where the file associated with this pane + * has been modified. + * @return the last modified time or 0 + */ + public long getLastModified() { + return lastModified; + } + + /** + * Set the last time where the file associated with this pane + * has been modified. + * @param time the time + */ + public void setLastModified(long time) { + this.lastModified = time; + ScilabEditorPane pane = getOtherPaneInSplit(); + if (pane != null) { + pane.lastModified = time; + } + } + + /** + * @return the SciNotesLineNumberPanel used with this pane + */ + public SciNotesLineNumberPanel getXln() { + return xln; + } + + /** + * @return the editor + */ + public SciNotes getEditor() { + return editor; + } + + /** + * @param editor to set + */ + public void setEditor(SciNotes editor) { + this.editor = editor; + } + + /** + * Disable all + */ + public void disableAll() { + indent = null; + tab = null; + com = null; + trailingWhite = null; + editor = null; + lexer = null; + helpOnTyping = null; + xln = null; + rightTextPane = null; + edComponent = null; + enableMatchingKeywords(false); + enableMatchingOpeners(false); + if (matchLR != null) { + matchLR.desactivateMouseOver(); + matchLR = null; + } + if (matchRL != null) { + matchRL.desactivateMouseOver(); + matchRL = null; + } + kwListeners = null; + } + + /** + * Destroy this component + */ + public void destroy() { + close(); + disableAll(); + } + + /** + * @return the scrollPane or the splitpane associated with this textPane + */ + public EditorComponent getEditorComponent() { + return edComponent; + } + + /** + * @return the scrollPane or the splitpane associated with this textPane + */ + public void setEditorComponent(EditorComponent ed) { + this.edComponent = ed; + } + + /** + * @param split the split used + */ + public void setSplitPane(JSplitPane split) { + edComponent.setSplitPane(split); + } + + /** + * @param split the split used + */ + public JSplitPane getSplitPane() { + return edComponent.getSplitPane(); + } + + /** + * Update the title of current tab + */ + public void updateTitle() { + if (editor != null) { + int index = editor.getTextPaneIndex(this); + if (index != -1) { + editor.updateTabTitle(index); + } + } + } + + public void setMustAdjustVisibility(boolean mustAdjustVisibility) { + ((ScilabCaret) getCaret()).setMustAdjustVisibility(mustAdjustVisibility); + } + + public boolean getMustAdjustVisibility() { + return ((ScilabCaret) getCaret()).getMustAdjustVisibility(); + } + + /** + * Scroll the pane to have the line containing pos on the top of the pane + * @param pos the position in the document + */ + public void scrollTextToPos(int pos) { + scrollTextToPos(pos, true, false); + } + + /** + * Scroll the pane to have the line containing pos on the top or centered on the pane + * @param pos the position in the document + * @param setCaret, if true the caret is set at the given position + * @param centered, if true the line is centered + */ + public void scrollTextToPos(final int pos, final boolean setCaret, final boolean centered) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + if (setCaret) { + setCaretPosition(pos); + } + JScrollBar scrollbar = getScrollPane().getVerticalScrollBar(); + Rectangle rect = modelToView(pos); + if (centered) { + int value = scrollbar.getValue(); + int h = scrollbar.getHeight(); + if (rect.y < value || rect.y > value + h) { + scrollbar.setValue(Math.max(0, rect.y - h / 2)); + } + } else { + if (rect.y > scrollbar.getMaximum()) { + scrollbar.setMaximum(rect.y); + } + scrollbar.setValue(rect.y); + } + } catch (BadLocationException e) { } + } + }); + } + + /** + * Scroll the pane to have the line lineNumber on the top of the pane + * @param lineNumber the number of the line + * @param highlight true to highlight the line + */ + public void scrollTextToLineNumber(int lineNumber, boolean highlight) { + scrollTextToLineNumber(lineNumber, highlight, true, false); + } + + /** + * Scroll the pane to have the line lineNumber on the top or centered on the pane + * @param lineNumber the number of the line + * @param highlight true to highlight the line + * @param setCaret, if true the caret is set at the given line + * @param centered, if true the line is centered + */ + public void scrollTextToLineNumber(int lineNumber, final boolean highlight, final boolean setCaret, final boolean centered) { + Element root = getDocument().getDefaultRootElement(); + if (lineNumber >= 1 && lineNumber <= root.getElementCount()) { + final int pos = root.getElement(lineNumber - 1).getStartOffset(); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + scrollTextToPos(pos, setCaret, centered); + if (highlight) { + saveHighlightContourColor = highlightContourColor; + highlightContourColor = null; + saveHighlightColor = highlightColor; + highlightColor = Color.YELLOW; + saveHighlightEnable = highlightEnable; + hasBeenSaved = true; + enableHighlightedLine(false); + enableHighlightedLine(true); + } + } + }); + } + } + + /** + * Scroll the pane to have the line lineNumber on the top of the pane in whereami mode + * The line number is computed regarding the function named funname. + * @param lineNumber the number of the line + * @param funname the function name + * @param highlight true to highlight the line + */ + public void scrollTextToLineNumberInWhereami(int lineNumber, String funname, boolean highlight) { + scrollTextToLineNumberInWhereami(lineNumber, funname, highlight, true, false); + } + + /** + * Scroll the pane to have the line lineNumber on the top of the pane in whereami mode + * The line number is computed regarding the function named funname. + * @param lineNumber the number of the line + * @param funname the function name + * @param highlight true to highlight the line + * @param setCaret, if true the caret is set at the given line + * @param centered, if true the line is centered + */ + public void scrollTextToLineNumberInWhereami(int lineNumber, String funname, boolean highlight, boolean setCaret, boolean centered) { + if (funname != null) { + Element root = getDocument().getDefaultRootElement(); + int nlines = root.getElementCount(); + ScilabDocument.ScilabLeafElement elem; + for (int i = 0; i < nlines; i++) { + elem = (ScilabDocument.ScilabLeafElement) root.getElement(i); + if (elem.getFunctionName().equals(funname)) { + lineNumber += i; + break; + } + } + } + scrollTextToLineNumber(lineNumber, highlight, setCaret, centered); + } + + /** + * @return the width of a white + */ + public int getWhiteWidth() { + View view = ((ScilabDocument) getDocument()).getView(); + if (view != null) { + if (view instanceof ScilabView) { + return ((ScilabView) view).getWhiteWidth(); + } else { + return ((ScilabPlainView) view).getWhiteWidth(); + } + } + + return 0; + } + + public void resetFont() { + Font font = ((ScilabEditorKit) getEditorKit()).getStylePreferences().getBaseFont(); + setFont(font); + xln.updateFont(font); + } + + /** + * Set a new font + * @param keyword the type of keyword + * @param type an int : -2 to reset italic, -1 to reset bold, 1 to set bold and 2 to set italic + */ + public void resetFont(String keyword, int type) { + ((ScilabEditorKit) getEditorKit()).getStylePreferences().genFont(keyword, type); + } + + /** + * Set a new attribute + * @param keyword the type of keyword + * @param type an int : 0 nothing, 1 underline, 2 stroke, 3 underline and stroke + */ + public void resetAttribute(String keyword, int type) { + ((ScilabEditorKit) getEditorKit()).getStylePreferences().genAttribute(keyword, type); + } + + /** + * Set a new color + * @param keyword the kind of the keyword + * @param color the color + */ + public void resetColor(String keyword, Color color) { + ((ScilabEditorKit) getEditorKit()).getStylePreferences().genColors(keyword, color); + } + + /** + * Set to true if the comments must be suppressed when the code is executing in the console + * @param b boolean + */ + public void suppressCommentsInExecutingCode(boolean b) { + suppressCom = b; + } + + /** + * Execute the code in the console, the code is the selected text if exists + * or the text from beginning to actual position of the caret + * Comments are removed if suppressCom is set to true + * @return the code to be executed in the console. + */ + public String getCodeToExecute() { + String selection; + int start, end; + start = getSelectionStart(); + end = getSelectionEnd(); + + if (((SciNotesCaret) getCaret()).isEmptySelection()) { + try { + if (start == end) { + selection = getDocument().getText(0, start); + start = 0; + } else { + selection = getSelectedText(); + } + } catch (BadLocationException e) { + selection = ""; + } + } else { + selection = getSelectedText(); + } + + if (suppressCom) { + StringBuffer buf = new StringBuffer(selection.length()); + ScilabLexer.ScilabTokens tokens = ScilabLexer.getScilabTokens(selection); + List<Integer> tokType = tokens.getTokenType(); + List<Integer> tokPos = tokens.getTokenPos(); + List<String> commands = new ArrayList<String>(); + int prevPos = 0; + for (int i = 0; i < tokType.size(); i++) { + String str = selection.substring(prevPos, tokPos.get(i)); + if ("\n".equals(str)) { + commands.add(buf.toString()); + buf.setLength(0); + } else if (!ScilabLexerConstants.isComment(tokType.get(i))) { + buf.append(str); + } + prevPos = tokPos.get(i); + } + + if (buf.length() != 0) { + commands.add(buf.toString()); + } + + buf.setLength(0); + Pattern pat = Pattern.compile("[ \t]*"); + for (String command : commands) { + if (!pat.matcher(command).matches()) { + buf.append(command).append("\n"); + } + } + + return buf.toString(); + } + + return selection; + } + + /** + * Add a new KeywordListener + * @param kw a KeywordListener + */ + public void addKeywordListener(KeywordListener kw) { + kwListeners.add(KeywordListener.class, kw); + } + + /** + * Remove a new KeywordListener + * @param kw a KeywordListener + */ + public void removeKeywordListener(KeywordListener kw) { + kwListeners.remove(KeywordListener.class, kw); + } + + /** + * @return an array of KeywordListener + */ + public KeywordListener[] getKeywordListeners() { + return kwListeners.getListeners(KeywordListener.class); + } + + /** + * Set a new color for the highlighting + * @param c the color, can be null (useful if setHighlightedContourColor is used with a + * non-null value) + */ + public void setHighlightedLineColor(Color c) { + highlightColor = c; + } + + /** + * Set a new color for the contour of the highlighting + * @param c the color, if null no contour is drawn + */ + public void setHighlightedContourColor(Color c) { + highlightContourColor = c; + } + + /** + * Activate or desactivate the help on typing + */ + public void activateHelpOnTyping() { + boolean isActive = HelpOnTypingManager.getInstance().isActive(); + if (isActive && helpOnTyping == null) { + helpOnTyping = HelpOnTypingManager.getInstance(); + addKeyListener(helpOnTyping); + } else if (!isActive && helpOnTyping != null) { + removeKeyListener(helpOnTyping); + helpOnTyping = null; + } + } + + /** + * Enable (active true) or disable (active false) the line-highlighting. + * @param active true or false + */ + public void enableHighlightedLine(boolean active) { + if (active && !highlightEnable) { + try { + highlightCL = getHighlighter().addHighlight(0, 0, this); + } catch (BadLocationException e) { } + highlightEnable = true; + } + + if (!active && highlightEnable) { + getHighlighter().removeHighlight(highlightCL); + highlightEnable = false; + } + + repaint(); + } + + /** + * Enable (active true) or disable (active false) the matching keywords. + * @param active true or false + */ + public void enableMatchingKeywords(boolean active) { + matchingKeywordsEnable = active; + } + + /** + * Enable (active true) or disable (active false) the matching keywords. + * @param active true or false + */ + public void enableMatchingOpeners(boolean active) { + matchingOpenersEnable = active; + } + + /** + * Get a matching manager + * @param lr true if the LR matcher must be returned + * @return the MatchingBlockManager + */ + public MatchingBlockManager getMatchingBlockManager(boolean lr) { + if (lr) { + return matchLR; + } else { + return matchRL; + } + } + + /** + * This class listens to the caret event + * @param e event + */ + public void caretUpdate(CaretEvent e) { + if (hasBeenSaved) { + removeHighlightForLine(); + } + + if (hasFocus()) { + final String str = getSelectedText(); + if (str != null && str.length() != 0) { + if (selectionTimer == null) { + selectionTimer = new Timer(1000, new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + final String str = getSelectedText(); + if (str != null && str.length() != 0) { + int tok = lexer.getKeyword(getSelectionStart(), false); + int s = lexer.start + lexer.yychar(); + if (ScilabLexerConstants.isSearchable(tok) && getSelectionStart() == s && getSelectionEnd() == s + lexer.yylength()) { + highlightWords(tok, SearchManager.generatePattern(str, false, true, false), false); + } else { + highlightWords(str, false); + } + + if (highlightedWords.size() > 1 && editor != null && editor.getInfoBar() != null) { + editor.getInfoBar().setText(String.format(SciNotesMessages.OCCURENCES_FOUND, Integer.toString(highlightedWords.size()))); + } + removeHighlightOnPosition(getSelectionStart()); + } + } catch (Exception ee) { } + selectionTimer = null; + } + }); + selectionTimer.setRepeats(false); + selectionTimer.start(); + } else { + selectionTimer.restart(); + } + } else { + removeHighlightedWords(); + } + } + + if (highlightEnable) { + repaint(); + } + + if (matchingKeywordsEnable || matchingOpenersEnable) { + if (matcherTimer == null) { + matcherTimer = new Timer(100, new ActionListener() { + public void actionPerformed(ActionEvent e) { + int pos = getCaretPosition(); + int tok = lexer.getKeyword(pos, false); + matchLR.searchMatchingBlock(false, tok, lexer.start + lexer.yychar()); + tok = lexer.getKeyword(pos, true); + matchRL.searchMatchingBlock(false, tok, lexer.start + lexer.yychar() + lexer.yylength()); + matcherTimer = null; + } + }); + matcherTimer.setRepeats(false); + matcherTimer.start(); + } else { + matcherTimer.restart(); + matchLR.update(); + matchRL.update(); + } + } + + if (!readonly && !binary && editor != null) { + editor.getInfoBar().setText(((ScilabDocument) getDocument()).getCurrentFunction(getCaretPosition())); + } + } + + /** + * Used to paint the highlighted line + * @param g graphics to use + * @param p0 start + * @param p1 end + * @param bounds the shape representing the area + * @param c this pane + */ + public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) { + if (highlightEnable) { + try { + Rectangle r = modelToView(getCaretPosition()); + if (highlightColor != null) { + g.setColor(highlightColor); + g.fillRect(0, r.y, getWidth(), r.height); + } + if (highlightContourColor != null) { + g.setColor(highlightContourColor); + g.drawLine(0, r.y - 1, getWidth(), r.y - 1); + g.drawLine(0, r.y + r.height, getWidth(), r.y + r.height); + } + + } catch (BadLocationException e) { } + } + } + + /** + * @return the current TrailingWhiteManager + */ + public TrailingWhiteManager getTrailingWhiteManager() { + return trailingWhite; + } + + /** + * @return the current IndentManager + */ + public IndentManager getIndentManager() { + return indent; + } + + /** + * @return the current TabManager + */ + public TabManager getTabManager() { + return tab; + } + + /** + * @return the current CommentManager + */ + public CommentManager getCommentManager() { + return com; + } + + /** + * Get a keyword at a position in the document. + * @param position in the document + * @return the KeywordEvent containing infos about keyword. + */ + public KeywordEvent getKeywordEvent(int position) { + int tok = lexer.getKeyword(position, true); + return new KeywordEvent(this, null, tok, lexer.start + lexer.yychar(), lexer.yylength()); + } + + /** + * Get a keyword at the current position in the document. + * @return the KeywordEvent containing infos about keyword. + */ + public KeywordEvent getKeywordEvent() { + return getKeywordEvent(getCaretPosition()); + } + + /** + * Get a keyword at the current position in the document. + * @param caret if true the position is the current caret position in the doc else + * the position is the mouse pointer position projected in the document. + * @param strict if true the char just after the caret is ignored + * @return the KeywordEvent containing infos about keyword. + */ + public KeywordEvent getKeywordEvent(boolean caret, boolean strict) { + int tok; + if (caret) { + tok = lexer.getKeyword(getCaretPosition(), strict); + } else { + tok = lexer.getKeyword(viewToModel(mousePoint), strict); + } + return new KeywordEvent(this, null, tok, lexer.start + lexer.yychar(), lexer.yylength()); + } + + /** + * Get an helpable keyword at the current position in the document. + * @param caret if true the position is the current caret position in the doc else + * the position is the mouse pointer position projected in the document. + * @return the helpable keyword. + */ + public String getHelpableKeyword(boolean caret) { + int tok; + int pos; + if (caret) { + pos = getCaretPosition(); + } else { + pos = viewToModel(mousePoint); + } + + tok = lexer.getKeyword(pos, true); + if (!ScilabLexerConstants.isHelpable(tok)) { + tok = lexer.getKeyword(pos + 1, true); + } + + if (ScilabLexerConstants.isHelpable(tok)) { + try { + return getDocument().getText(lexer.start + lexer.yychar(), lexer.yylength()); + } catch (BadLocationException e) { } + } + + return null; + } + + /** + * Prevents the different KeywordListener that a MouseEvent occurred + * @param position of the mouse + * @param ev the event which occurred + * @param type of the event : KeywordListener.ONMOUSECLICKED or KeywordListener.ONMOUSEOVER + */ + protected void preventConcernedKeywordListener(int position, EventObject ev, int type) { + KeywordEvent kev = null; + Object[] listeners = kwListeners.getListenerList(); + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == KeywordListener.class && type == ((KeywordListener) listeners[i + 1]).getType()) { + if (kev == null) { + int tok = lexer.getKeyword(position, true); + kev = new KeywordEvent(this, ev, tok, lexer.start + lexer.yychar(), lexer.yylength()); + } + + ((KeywordListener) listeners[i + 1]).caughtKeyword(kev); + } + } + } + + /** + * Implements mouseClicked in MouseListener + * @param e event + */ + public void mouseClicked(MouseEvent e) { + preventConcernedKeywordListener(getCaretPosition(), e, KeywordListener.ONMOUSECLICKED); + } + + /** + * Implements mouseEntered in MouseListener + * @param e event + */ + public void mouseEntered(MouseEvent e) { + this.mousePoint = e.getPoint(); + } + + /** + * Implements mouseExited in MouseListener + * @param e event + */ + public void mouseExited(MouseEvent e) { } + + /** + * Implements mousePressed in MouseListener + * @param e event + */ + public void mousePressed(MouseEvent e) { + if (hasBeenSaved) { + removeHighlightForLine(); + } + + removeHighlightedWords(); + + if (highlightEnable) { + repaint(); + } + } + + /** + * Implements mouseReleseaed in MouseListener + * @param e event + */ + public void mouseReleased(MouseEvent e) { } + + /** + * Implements mouseMoved in MouseMotionListener + * @param e event + */ + public void mouseMoved(MouseEvent e) { + this.mousePoint = e.getPoint(); + preventConcernedKeywordListener(viewToModel(mousePoint), e, KeywordListener.ONMOUSEOVER); + } + + /** + * Implements mouseDragged in MouseMotionListener + * @param e event + */ + public void mouseDragged(MouseEvent e) { + if (hasBeenSaved) { + removeHighlightForLine(); + } + + removeHighlightedWords(); + + if (highlightEnable) { + repaint(); + } + } + + /** + * @return the current mouse poisition in this pane + */ + public Point getMousePoint() { + return mousePoint; + } + + /** + * @param pane the EditorPane associated with this EditorPane in a splitted view + */ + public void setOtherPaneInSplit(ScilabEditorPane pane) { + if (pane == null) { + rightTextPane.rightTextPane = null; + } + rightTextPane = pane; + } + + /** + * @return the EditorPane associated with this EditorPane in a splitted view + */ + public ScilabEditorPane getOtherPaneInSplit() { + return rightTextPane; + } + + public ScilabEditorPane getCurrent() { + if (focused == rightTextPane) { + return rightTextPane; + } + + return this; + } + + + /** + * @return the scrollPane associated with this EditorPane + */ + public ScilabScrollPane getScrollPane() { + return (ScilabScrollPane) SwingUtilities.getAncestorOfClass(ScilabScrollPane.class, this); + } + + /** + * @return the current focused editorPane + */ + public static ScilabEditorPane getFocusedPane() { + return focused; + } + + /** + * clean + */ + public static void clean() { + focused = null; + } + + /** + * {@inheritDoc} + */ + public String toString() { + return shortName; + } + + /** + * @return true if something has been copied + */ + public boolean copyColumnSelectionInClipBoard() { + return ((SciNotesCaret) getCaret()).copyPositionsInClipboard(); + } + + /** + * @return true if something has been removed + */ + public boolean removeColumnSelection() { + return ((SciNotesCaret) getCaret()).removePositions(); + } + + /** + * {@inheritDoc} + */ + public String getSelectedText() { + if (getCaret() instanceof SciNotesCaret) { + String str = ((SciNotesCaret) getCaret()).getSelectedText(); + if (str == null) { + return super.getSelectedText(); + } else { + return str; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public int getCaretPosition() { + if (getCaret() != null) { + return super.getCaretPosition(); + } + + return 0; + } + + /** + * @param pos the position int the text + * @return null if no column selection on the same line and an array of + * integer (of size 2) containing the position of the selection + */ + public int[] isNearColumnSelection(int pos) { + if (!(getCaret() instanceof SciNotesCaret) || ((SciNotesCaret) getCaret()).isEmptySelection()) { + return null; + } + + Element root = getDocument().getDefaultRootElement(); + int[][] positions = ((SciNotesCaret) getCaret()).getSelectedPositions(); + int line = root.getElementIndex(pos); + int min = root.getElementIndex(positions[0][0]); + int max = root.getElementIndex(positions[positions.length - 1][0]); + + if (line >= min && line <= max) { + return positions[line - min]; + } + + return null; + } + + /** + * {@inheritDoc} + */ + public void setCaret(Caret c) { + if (!(c instanceof ScilabCaret)) { + final Caret caret = new SciNotesCaret(this); + setCaretColor(getCaretColor()); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + int blinkRate = 500; + Object o = UIManager.get("TextComponent.caretBlinkRate"); + if ((o != null) && (o instanceof Integer)) { + Integer rate = (Integer) o; + blinkRate = rate.intValue(); + } + caret.setBlinkRate(blinkRate); + caret.setVisible(true); + } + }); + super.setCaret(caret); + } else { + super.setCaret(c); + } + } + + /** + * {@inheritDoc} + */ + public void select(int start, int end) { + removeHighlightOnPosition(start); + int docLength = getDocument().getLength(); + if (start > docLength) { + start = docLength; + } + if (end > docLength) { + end = docLength; + } + super.setCaretPosition(start); + super.moveCaretPosition(end); + } + + /** + * Remove the highlight putted to show the line (for editor('foo',123)) + */ + private void removeHighlightForLine() { + highlightContourColor = saveHighlightContourColor; + highlightColor = saveHighlightColor; + enableHighlightedLine(false); + if (saveHighlightEnable) { + enableHighlightedLine(true); + } + hasBeenSaved = false; + } + + /** + * Remove the highlight at position start + * @param start the beginning of the highlight + */ + public void removeHighlightOnPosition(int start) { + Object h = highlightedWords.get(start); + if (h != null) { + getHighlighter().removeHighlight(h); + highlightedWords.remove(h); + } + } + + /** + * Highlight a word in this textpane. + * @param word the word to highlight + * @param exact if true the search is case sensitive + */ + public void highlightWords(String word, boolean exact) { + if (word != null && word.length() != 0) { + highlightWords(SearchManager.generatePattern(word, exact, false, false), false); + } + } + + /** + * Highlight a word according to a pattern in this textpane. + * @param pattern the pattern to highlight + * @param centered, if true the pane is centered on the first occurence + */ + public void highlightWords(Pattern pattern, boolean centered) { + highlightWords(-1, pattern, centered); + } + + /** + * Highlight a word according to a pattern in this textpane. + * @param pattern the pattern to highlight + * @param centered, if true the pane is centered on the first occurence + */ + public void highlightWords(int tok, Pattern pattern, boolean centered) { + if (pattern != null) { + removeHighlightedWords(); + int first = -1; + String text = ((ScilabDocument) getDocument()).getText(); + Matcher matcher = pattern.matcher(text); + + Highlighter highlighter = getHighlighter(); + List<Integer[]> positions = SearchManager.findToken((ScilabDocument) getDocument(), tok, lexer, pattern); + + if (positions != null) { + List<Rectangle> marks = new ArrayList<Rectangle>(); + + for (Integer[] position : positions) { + try { + highlightedWords.put(position[0], highlighter.addHighlight(position[0], position[1], HIGHLIGHTER)); + Rectangle r = modelToView(position[0]); + if (r != null && (marks.size() == 0 || marks.get(marks.size() - 1).y != r.y)) { + marks.add(r); + } + } catch (BadLocationException e) { } + } + + ScilabScrollPane ssp = getScrollPane(); + if (ssp != null) { + ssp.putMarks(marks); + } + + if (centered && positions.size() != 0) { + scrollTextToPos(positions.get(0)[0], false, true); + } + } + } + } + + /** + * Remove all the highlighted words + */ + public void removeHighlightedWords() { + Highlighter highlighter = getHighlighter(); + for (Object obj : highlightedWords.values()) { + highlighter.removeHighlight(obj); + } + highlightedWords.clear(); + ScilabScrollPane ssp = getScrollPane(); + if (ssp != null) { + ssp.removeMarks(); + } + } + + /** + * Initialize the pane when the document is loaded + * @param doc used with this pane + */ + private void initialize(ScilabDocument doc) { + indent = new IndentManager(doc); + tab = new TabManager(doc, indent); + tab.setDefaultTabulation(); + com = new CommentManager(doc); + trailingWhite = new TrailingWhiteManager(doc); + + if (matchingKeywordsEnable || matchingOpenersEnable) { + matchLR = new MatchingBlockManager(doc, this, true, getHighlighter()); + matchLR.setDefaults(); + matchRL = new MatchingBlockManager(doc, this, false, getHighlighter()); + matchRL.setDefaults(); + } + + lexer = doc.createLexer(); + xln = new SciNotesLineNumberPanel(this); + + /* The order of the next two lines is important: the doc + as listener will be called before xln so the resetTypeWhenBroken + will be called before ! */ + doc.addDocumentListener(xln); + doc.addDocumentListener(doc); + + getScrollPane().setRowHeaderView(xln); + doc.setEditorPane(this); + + if (editor != null) { + NavigatorWindow nav = editor.getNavigator(); + if (nav != null) { + nav.addEditorPane(this); + } + } + + resetFont(); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabKeywords.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabKeywords.java new file mode 100755 index 000000000..6d5e992f5 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabKeywords.java @@ -0,0 +1,36 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package org.scilab.modules.scinotes; + + +/** + * @author Allan CORNET - DIGITEO 2009 + * @author Calixte DENIZET + */ +public class ScilabKeywords { + + /** + * Constructor + */ + protected ScilabKeywords() { + throw new UnsupportedOperationException(); + } + public static String[] GetVariablesName() { + return ScilabKeywordsJNI.GetVariablesName(); + } + + public static String[] GetFunctionsName() { + return ScilabKeywordsJNI.GetFunctionsName(); + } + + public static String[] GetMacrosName() { + return ScilabKeywordsJNI.GetMacrosName(); + } + +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabKeywordsJNI.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabKeywordsJNI.java new file mode 100755 index 000000000..86e754e76 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabKeywordsJNI.java @@ -0,0 +1,46 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package org.scilab.modules.scinotes; + + +/* It is generated code. Disable checkstyle */ +//CHECKSTYLE:OFF +/** + * @author Allan CORNET - DIGITEO 2009 + * @author Calixte DENIZET + */ +public class ScilabKeywordsJNI { + + /** + * Constructor + */ + protected ScilabKeywordsJNI() { + throw new UnsupportedOperationException(); + } + + static { + try { + System.loadLibrary("sciscinotes"); + } catch (SecurityException e) { + System.err.println("A security manager exists and does not allow the loading of the specified dynamic library."); + System.err.println(e.getLocalizedMessage()); + e.printStackTrace(System.err); + } catch (UnsatisfiedLinkError e) { + if (System.getenv("CONTINUE_ON_JNI_ERROR") == null) { + System.err.println("The native library scinotes does not exist or cannot be found."); + System.err.println(e.getLocalizedMessage()); + e.printStackTrace(System.err); + } + } + } + + public final static native String[] GetVariablesName(); + public final static native String[] GetFunctionsName(); + public final static native String[] GetMacrosName(); +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabLexer.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabLexer.java new file mode 100755 index 000000000..60ffdcef7 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabLexer.java @@ -0,0 +1,1633 @@ +/* The following code was generated by JFlex 1.4.3 on 02/05/14 11:47 */ + +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Iterator; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.io.IOException; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.commons.ScilabCommonsUtils; + +@javax.annotation.Generated("JFlex") +@SuppressWarnings("fallthrough") + + +/** + * This class is a scanner generated by + * <a href="http://www.jflex.de/">JFlex</a> 1.4.3 + * on 02/05/14 11:47 from the specification file + * <tt>scilab.jflex</tt> + */ +public final class ScilabLexer extends ScilabLexerConstants { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int BREAKSTRING = 12; + public static final int COMMANDSWHITE = 10; + public static final int YYINITIAL = 0; + public static final int COMMENT = 4; + public static final int FIELD = 6; + public static final int COMMANDS = 8; + public static final int QSTRING = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\110\1\1\1\0\1\120\1\113\22\0\1\72\1\116\1\7" + + "\1\114\1\112\1\10\1\51\1\6\1\3\1\4\1\40\1\43\1\117" + + "\1\44\1\37\1\5\12\115\1\111\1\124\1\47\1\45\1\50\1\114" + + "\1\53\1\100\1\101\1\25\1\35\1\33\1\14\1\103\1\30\1\26" + + "\1\102\1\107\1\76\1\32\1\73\1\31\1\34\1\106\1\36\1\24" + + "\1\12\1\77\1\104\1\27\2\122\1\74\1\2\1\41\1\4\1\42" + + "\1\121\1\0\1\23\1\65\1\55\1\57\1\15\1\13\1\105\1\60" + + "\1\17\1\122\1\66\1\61\1\70\1\20\1\56\1\16\1\67\1\62" + + "\1\22\1\11\1\54\1\75\1\63\1\71\1\64\1\21\1\2\1\52" + + "\1\4\1\46\u0511\0\160\123\u0100\123\120\0\60\123\100\123\100\123\uf31d\0" + + "\63\123\u02b0\123\160\0\220\123\u0100\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\1\0\1\1\3\0\1\1\1\0\1\2\1\3\1\4" + + "\1\5\1\6\1\7\14\10\1\11\11\5\6\10\1\12" + + "\1\13\2\14\1\15\1\2\1\1\1\16\1\17\1\1" + + "\1\20\1\21\1\1\1\22\1\23\17\22\1\24\4\22" + + "\1\25\2\22\1\26\1\27\1\26\1\30\1\31\1\32" + + "\1\33\2\1\1\34\1\35\2\16\1\36\1\5\1\37" + + "\1\0\2\40\1\10\1\40\12\10\1\41\4\10\1\5" + + "\1\14\1\5\1\15\2\0\2\10\1\42\3\10\1\0" + + "\1\37\2\0\1\37\1\15\3\0\27\22\1\0\13\22" + + "\1\0\1\1\1\43\3\0\6\10\1\41\5\10\1\40" + + "\1\10\1\15\7\10\2\15\1\44\2\0\30\22\1\0" + + "\10\22\1\0\2\22\1\0\1\45\3\10\1\46\1\47" + + "\11\10\21\22\1\50\4\22\1\0\10\22\2\0\1\22" + + "\1\51\1\45\7\10\1\0\1\52\14\22\1\0\3\22" + + "\1\0\10\22\1\0\2\51\1\10\1\46\2\10\1\22" + + "\2\0\11\22\1\0\3\22\1\0\5\22\1\0\2\22" + + "\1\51\1\10\1\53\3\0\2\22\1\0\3\22\4\0" + + "\1\22\1\0\5\22\1\0\2\22\1\54\6\0\1\22" + + "\2\0\1\22\5\0\1\22\1\55\2\0\1\22\4\0" + + "\1\22\3\0\1\22\6\0\1\22\3\0\1\22\7\0" + + "\1\22\1\55\1\0\1\22\4\0\1\22\3\0\1\22" + + "\22\0\1\22\1\0\1\22\14\0\1\50\22\0\1\22" + + "\34\0\1\22\30\0\1\55\22\0\3\55\11\0\2\55" + + "\7\0\2\55\2\0\2\37\1\55"; + + private static int [] zzUnpackAction() { + int [] result = new int[598]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do { + result[j++] = value; + } while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\125\0\252\0\377\0\u0154\0\u01a9\0\u01fe\0\u0253" + + "\0\u0253\0\u0253\0\u02a8\0\u02fd\0\u02fd\0\u0352\0\u03a7\0\u03fc" + + "\0\u0451\0\u04a6\0\u04fb\0\u0550\0\u05a5\0\u05fa\0\u064f\0\u06a4" + + "\0\u06f9\0\u074e\0\u07a3\0\u07f8\0\u084d\0\u08a2\0\u08f7\0\u094c" + + "\0\u09a1\0\u09f6\0\u0a4b\0\u0aa0\0\u0af5\0\u0b4a\0\u0b9f\0\u0bf4" + + "\0\u0c49\0\u0c9e\0\u0cf3\0\u07f8\0\u04a6\0\u0d48\0\u07f8\0\u0d9d" + + "\0\u0253\0\u0df2\0\u0e47\0\u0253\0\u0253\0\u0e9c\0\u0ef1\0\u0253" + + "\0\u0f46\0\u0f9b\0\u0ff0\0\u1045\0\u109a\0\u10ef\0\u1144\0\u1199" + + "\0\u11ee\0\u1243\0\u1298\0\u12ed\0\u1342\0\u1397\0\u13ec\0\u0253" + + "\0\u1441\0\u1496\0\u14eb\0\u1540\0\u0253\0\u1595\0\u15ea\0\u0253" + + "\0\u163f\0\u163f\0\u0253\0\u0253\0\u1694\0\u1694\0\u16e9\0\u173e" + + "\0\u0253\0\u0253\0\u1793\0\u17e8\0\u0253\0\u0253\0\u0253\0\u183d" + + "\0\u04a6\0\u1892\0\u18e7\0\u193c\0\u1991\0\u19e6\0\u1a3b\0\u1a90" + + "\0\u1ae5\0\u1b3a\0\u1b8f\0\u1be4\0\u1c39\0\u1c8e\0\u04a6\0\u1ce3" + + "\0\u1d38\0\u1d8d\0\u1de2\0\u1e37\0\u1e8c\0\u1ee1\0\u1f36\0\u1f8b" + + "\0\u1fe0\0\u2035\0\u208a\0\u04a6\0\u20df\0\u2134\0\u2189\0\u21de" + + "\0\u2233\0\u07f8\0\u0cf3\0\u2288\0\u22dd\0\u0df2\0\u2332\0\u2387" + + "\0\u23dc\0\u2431\0\u2486\0\u24db\0\u2530\0\u2585\0\u25da\0\u262f" + + "\0\u2684\0\u26d9\0\u272e\0\u2783\0\u27d8\0\u282d\0\u2882\0\u28d7" + + "\0\u292c\0\u2981\0\u29d6\0\u2a2b\0\u2a80\0\u2ad5\0\u2b2a\0\u2b7f" + + "\0\u2bd4\0\u2c29\0\u2c7e\0\u2cd3\0\u2d28\0\u2d7d\0\u2dd2\0\u2e27" + + "\0\u2e7c\0\u2ed1\0\u2f26\0\u1694\0\u2f7b\0\u17e8\0\u2fd0\0\u3025" + + "\0\u307a\0\u30cf\0\u3124\0\u3179\0\u31ce\0\u3223\0\u3278\0\u32cd" + + "\0\u3322\0\u3377\0\u33cc\0\u3421\0\u3476\0\u34cb\0\u3520\0\u3575" + + "\0\u35ca\0\u361f\0\u3674\0\u36c9\0\u371e\0\u3773\0\u37c8\0\u381d" + + "\0\u3872\0\u0253\0\u38c7\0\u391c\0\u3971\0\u39c6\0\u3a1b\0\u3a70" + + "\0\u3ac5\0\u3b1a\0\u3b6f\0\u3bc4\0\u3c19\0\u3c6e\0\u3cc3\0\u3d18" + + "\0\u3d6d\0\u3dc2\0\u3e17\0\u3e6c\0\u3ec1\0\u3f16\0\u3f6b\0\u3fc0" + + "\0\u4015\0\u406a\0\u40bf\0\u4114\0\u4169\0\u41be\0\u4213\0\u4268" + + "\0\u42bd\0\u4312\0\u4367\0\u43bc\0\u4411\0\u4466\0\u44bb\0\u4510" + + "\0\u4565\0\u0253\0\u45ba\0\u460f\0\u4664\0\u46b9\0\u04a6\0\u470e" + + "\0\u4763\0\u47b8\0\u480d\0\u4862\0\u48b7\0\u490c\0\u4961\0\u49b6" + + "\0\u4a0b\0\u4a60\0\u4ab5\0\u4b0a\0\u4b5f\0\u4bb4\0\u4c09\0\u4c5e" + + "\0\u4cb3\0\u4d08\0\u4d5d\0\u4db2\0\u4e07\0\u4e5c\0\u4eb1\0\u4f06" + + "\0\u4f5b\0\u0ef1\0\u4fb0\0\u5005\0\u505a\0\u50af\0\u5104\0\u5159" + + "\0\u51ae\0\u5203\0\u5258\0\u52ad\0\u5302\0\u5357\0\u53ac\0\u5401" + + "\0\u5456\0\u54ab\0\u0ef1\0\u2fd0\0\u5500\0\u5555\0\u55aa\0\u55ff" + + "\0\u5654\0\u56a9\0\u56fe\0\u5753\0\u57a8\0\u57fd\0\u5852\0\u58a7" + + "\0\u58fc\0\u5951\0\u59a6\0\u59fb\0\u5a50\0\u5aa5\0\u5afa\0\u5b4f" + + "\0\u5ba4\0\u5bf9\0\u5c4e\0\u5ca3\0\u5cf8\0\u5d4d\0\u5da2\0\u5df7" + + "\0\u5e4c\0\u5ea1\0\u5ef6\0\u5f4b\0\u5fa0\0\u5ff5\0\u604a\0\u0253" + + "\0\u4510\0\u609f\0\u04a6\0\u60f4\0\u6149\0\u619e\0\u61f3\0\u6248" + + "\0\u629d\0\u62f2\0\u6347\0\u639c\0\u63f1\0\u6446\0\u649b\0\u64f0" + + "\0\u6545\0\u659a\0\u65ef\0\u6644\0\u6699\0\u66ee\0\u6743\0\u6798" + + "\0\u67ed\0\u6842\0\u6897\0\u68ec\0\u6941\0\u6996\0\u5456\0\u69eb" + + "\0\u619e\0\u6a40\0\u6a95\0\u6aea\0\u6b3f\0\u6b94\0\u6be9\0\u6c3e" + + "\0\u6c93\0\u6ce8\0\u6d3d\0\u6d92\0\u6de7\0\u6e3c\0\u6e91\0\u6ee6" + + "\0\u6f3b\0\u6f90\0\u6fe5\0\u703a\0\u708f\0\u70e4\0\u7139\0\u718e" + + "\0\u04a6\0\u71e3\0\u7238\0\u728d\0\u72e2\0\u7337\0\u738c\0\u73e1" + + "\0\u7436\0\u748b\0\u74e0\0\u7535\0\u758a\0\u75df\0\u7634\0\u7689" + + "\0\u76de\0\u0ef1\0\u7733\0\u7788\0\u77dd\0\u7832\0\u7887\0\u78dc" + + "\0\u7931\0\u7986\0\u79db\0\u7a30\0\u7a85\0\u7ada\0\u7b2f\0\u7b84" + + "\0\u7bd9\0\u7c2e\0\u7c83\0\u7cd8\0\u7d2d\0\u7d82\0\u7dd7\0\u7e2c" + + "\0\u7e81\0\u7ed6\0\u7f2b\0\u7f80\0\u7fd5\0\u802a\0\u807f\0\u80d4" + + "\0\u8129\0\u0253\0\u817e\0\u81d3\0\u8228\0\u827d\0\u82d2\0\u8327" + + "\0\u837c\0\u83d1\0\u8426\0\u847b\0\u84d0\0\u8525\0\u857a\0\u85cf" + + "\0\u8624\0\u8679\0\u86ce\0\u8723\0\u8778\0\u87cd\0\u8822\0\u8877" + + "\0\u88cc\0\u8921\0\u8976\0\u89cb\0\u8a20\0\u8a75\0\u8aca\0\u8b1f" + + "\0\u8b74\0\u8bc9\0\u8c1e\0\u8c73\0\u8cc8\0\u8d1d\0\u8d72\0\u8dc7" + + "\0\u8e1c\0\u8e71\0\u8ec6\0\u8f1b\0\u8f70\0\u8fc5\0\u0253\0\u901a" + + "\0\u906f\0\u90c4\0\u9119\0\u916e\0\u91c3\0\u9218\0\u926d\0\u92c2" + + "\0\u9317\0\u936c\0\u93c1\0\u9416\0\u946b\0\u94c0\0\u9515\0\u956a" + + "\0\u95bf\0\u9614\0\u9669\0\u96be\0\u9713\0\u9768\0\u97bd\0\u9812" + + "\0\u9867\0\u98bc\0\u9911\0\u9966\0\u99bb\0\u9a10\0\u9a65\0\u9aba" + + "\0\u9b0f\0\u9b64\0\u9bb9\0\u9c0e\0\u9c63\0\u9cb8\0\u9d0d\0\u9d62" + + "\0\u9db7\0\u9e0c\0\u9e61\0\u9eb6\0\u9f0b\0\u9f60\0\u9fb5\0\ua00a" + + "\0\ua05f\0\ua0b4\0\ua109\0\ua15e\0\ua1b3\0\ua208\0\ua25d\0\ua2b2" + + "\0\ua307\0\ua35c\0\ua3b1\0\ua406\0\ua45b\0\ua4b0\0\ua505\0\ua55a" + + "\0\ua5af\0\ua604\0\ua659\0\ua6ae\0\ua703\0\ua758\0\ua7ad\0\ua802" + + "\0\ua857\0\ua8ac\0\ua901\0\ua956\0\ua9ab\0\uaa00\0\uaa55\0\uaaaa" + + "\0\uaaff\0\uab54\0\uaba9\0\uabfe\0\uac53\0\uaca8\0\uacfd\0\uad52" + + "\0\uada7\0\uadfc\0\uae51\0\uaea6\0\uaefb\0\uaf50\0\uafa5\0\uaffa" + + "\0\ub04f\0\ub0a4\0\ub0f9\0\ub14e\0\ub1a3\0\ub1f8\0\ub24d\0\ub2a2" + + "\0\ub2f7\0\ub34c\0\ub3a1\0\ub3f6\0\ub44b\0\ub4a0\0\ub4f5\0\ub54a" + + "\0\ub59f\0\ub5f4\0\ub649\0\ua0b4\0\ub69e\0\ub6f3"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[598]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\2\10\2\11\1\12\1\13\1\14\1\15\1\16\1\17" + + "\1\20\1\21\1\22\1\23\1\24\1\25\2\22\1\26" + + "\1\27\1\30\2\22\1\31\7\22\1\32\1\33\2\34" + + "\1\35\1\36\1\37\1\40\1\41\1\40\1\42\1\43" + + "\1\40\1\22\1\44\1\22\1\45\2\22\1\46\1\47" + + "\1\22\1\50\1\22\1\51\2\22\1\52\15\22\1\53" + + "\1\54\1\55\1\10\1\22\1\56\1\22\1\57\1\10" + + "\2\22\2\10\1\60\1\61\4\60\2\62\27\60\1\63" + + "\32\60\1\64\15\60\1\65\2\60\1\61\7\60\1\66" + + "\1\60\1\67\1\70\7\67\1\71\1\72\1\73\6\67" + + "\1\74\1\67\1\75\1\76\1\77\3\67\1\100\1\101" + + "\1\102\1\103\11\67\1\104\7\67\1\105\1\106\7\67" + + "\1\107\1\67\1\110\3\67\1\111\1\67\1\112\1\113" + + "\2\67\1\114\3\67\1\115\1\67\1\116\10\67\1\117" + + "\1\67\10\120\27\121\15\120\16\121\1\120\15\121\2\120" + + "\1\122\1\120\1\121\1\120\1\121\2\120\2\121\3\120" + + "\1\123\1\120\1\124\66\120\1\125\15\120\1\126\14\120" + + "\5\127\1\130\64\127\1\131\15\127\1\132\6\127\1\120" + + "\4\127\1\120\5\61\1\133\31\61\1\134\32\61\1\131" + + "\15\61\1\132\14\61\132\0\1\135\31\0\1\136\5\0" + + "\1\137\171\0\1\140\23\0\4\141\1\142\1\143\1\144" + + "\1\145\2\141\14\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\26\22\15\0" + + "\4\22\1\146\1\22\1\147\7\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\21\22\1\150" + + "\4\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\26\22\15\0\1\151\1\22" + + "\1\152\13\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\13\0\26\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\7\22" + + "\1\153\16\22\15\0\5\22\1\154\7\22\1\155\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\12\22\1\156\13\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\2\22\1\157" + + "\23\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\4\22\1\160\21\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\26\22\15\0\11\22\1\161\4\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\14\22\1\162\11\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\13\22\1\163" + + "\12\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\7\0\1\164\1\136\30\0\1\165" + + "\1\166\1\164\1\136\2\0\1\137\47\0\1\167\47\0" + + "\1\136\4\0\1\137\124\0\1\137\64\0\1\137\31\0" + + "\1\170\3\137\2\0\1\137\64\0\1\137\31\0\1\170" + + "\3\137\2\0\1\137\2\0\1\137\121\0\1\136\1\0" + + "\2\137\21\0\1\171\15\0\1\171\61\0\1\136\124\0" + + "\1\136\2\0\1\136\125\0\1\137\125\0\1\137\63\0" + + "\12\22\1\172\13\22\15\0\2\22\1\173\13\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\26\22\15\0\2\22\1\174\13\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\4\22\1\175" + + "\21\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\26\22\15\0\4\22\1\176" + + "\11\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\26\22\15\0\6\22\1\177\7\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\26\22\15\0\1\155\15\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\74\0\1\200\15\0\1\201" + + "\5\0\1\202\100\0\1\201\15\0\1\203\25\0\4\204" + + "\1\205\15\204\1\205\1\204\1\205\1\204\1\167\14\0" + + "\3\204\1\205\12\204\1\0\15\204\2\0\1\204\1\0" + + "\1\204\1\56\1\204\2\0\2\204\2\0\1\60\1\0" + + "\4\60\2\206\27\60\1\0\32\60\1\0\15\60\1\0" + + "\2\60\1\0\11\60\6\0\2\60\154\0\1\207\65\0" + + "\1\66\1\0\4\66\2\210\27\66\1\0\53\66\1\0" + + "\11\66\1\67\1\0\70\67\1\0\15\67\1\0\15\67" + + "\1\0\54\67\1\211\13\67\1\0\15\67\1\0\15\67" + + "\1\0\27\67\1\212\24\67\1\211\13\67\1\0\15\67" + + "\1\0\15\67\1\0\7\67\1\213\5\67\1\214\52\67" + + "\1\0\15\67\1\0\15\67\1\0\11\67\1\215\54\67" + + "\1\216\1\67\1\0\15\67\1\0\15\67\1\0\13\67" + + "\1\217\1\67\1\220\35\67\1\221\2\67\1\222\3\67" + + "\1\223\5\67\1\0\15\67\1\0\15\67\1\0\13\67" + + "\1\224\5\67\1\225\34\67\1\226\1\227\10\67\1\0" + + "\15\67\1\0\15\67\1\0\16\67\1\230\51\67\1\0" + + "\1\231\14\67\1\0\15\67\1\0\21\67\1\232\46\67" + + "\1\0\15\67\1\0\15\67\1\0\70\67\1\0\1\233" + + "\14\67\1\0\15\67\1\0\21\67\1\234\46\67\1\0" + + "\15\67\1\0\15\67\1\0\15\67\1\235\6\67\1\236" + + "\43\67\1\0\15\67\1\0\15\67\1\0\7\67\27\237" + + "\4\67\1\237\7\67\16\237\1\240\15\237\1\240\4\67" + + "\1\237\3\67\2\237\3\67\1\0\21\67\1\241\46\67" + + "\1\0\15\67\1\0\15\67\1\0\7\67\1\242\60\67" + + "\1\0\15\67\1\0\15\67\1\0\21\67\1\243\46\67" + + "\1\0\15\67\1\0\15\67\1\0\13\67\1\244\54\67" + + "\1\0\15\67\1\0\15\67\1\0\16\67\1\245\36\67" + + "\1\246\1\67\1\247\10\67\1\0\15\67\1\0\15\67" + + "\1\0\60\67\1\250\7\67\1\0\15\67\1\0\15\67" + + "\1\0\15\67\1\251\41\67\1\252\10\67\1\0\15\67" + + "\1\0\15\67\1\0\70\67\1\0\15\67\1\0\1\67" + + "\1\253\12\67\1\117\1\0\123\117\11\0\26\121\15\0" + + "\16\121\1\0\15\121\2\0\1\121\1\0\3\121\2\0" + + "\2\121\5\0\1\124\66\0\1\254\15\0\1\254\14\0" + + "\5\127\1\0\64\127\1\0\15\127\1\0\6\127\1\0" + + "\4\127\1\0\5\255\1\135\64\255\1\0\32\255\5\0" + + "\1\135\156\0\1\256\65\0\6\140\2\257\31\140\1\260" + + "\50\140\1\261\12\140\11\0\5\22\1\262\20\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\6\22\1\141\17\22\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\7\22\1\263\16\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\12\22\1\264" + + "\13\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\4\22\1\265\21\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\26\22\15\0\10\22\1\157\5\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\23\22\1\266\2\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\7\22\1\267" + + "\16\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\26\22\15\0\6\22\1\157" + + "\7\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\26\22\15\0\3\22\1\270\12\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\11\22\1\271\14\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\6\22\1\272" + + "\17\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\26\22\15\0\1\273\15\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\13\0\26\22\15\0\5\22\1\274\10\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\26\22" + + "\15\0\2\22\1\275\13\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\15\22\1\276\10\22" + + "\15\0\16\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\13\0\14\22\1\277\11\22\15\0\16\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\41\0\1\136\124\0\1\165\124\0\2\136\101\0\1\300" + + "\15\0\1\300\1\0\1\300\21\0\1\300\35\0\1\167" + + "\14\0\1\137\32\0\5\137\127\0\2\137\21\0\1\171" + + "\15\0\1\171\25\0\1\301\10\22\1\302\14\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\7\22\1\303\16\22\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\1\304\10\22\1\305\14\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\6\22" + + "\1\306\17\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\4\22\1\307\21\22" + + "\15\0\16\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\74\0\1\200\15\0\1\201\106\0\1\201" + + "\15\0\1\201\25\0\26\204\15\0\16\204\1\0\15\204" + + "\2\0\1\204\1\0\3\204\2\0\2\204\13\0\26\204" + + "\4\0\2\310\7\0\16\204\1\0\15\204\2\0\1\204" + + "\1\0\1\204\1\311\1\204\2\0\2\204\3\0\1\312" + + "\3\0\1\313\31\0\1\207\32\0\1\314\15\0\1\314" + + "\22\0\2\66\115\0\1\67\1\0\55\67\1\315\12\67" + + "\1\0\15\67\1\0\15\67\1\0\33\67\1\316\34\67" + + "\1\0\15\67\1\0\15\67\1\0\14\67\1\317\53\67" + + "\1\0\15\67\1\0\15\67\1\0\57\67\1\320\10\67" + + "\1\0\15\67\1\0\15\67\1\0\7\67\1\321\60\67" + + "\1\0\15\67\1\0\15\67\1\0\63\67\1\322\4\67" + + "\1\0\15\67\1\0\15\67\1\0\60\67\1\323\7\67" + + "\1\0\15\67\1\0\15\67\1\0\66\67\1\324\1\67" + + "\1\0\15\67\1\0\15\67\1\0\15\67\1\325\52\67" + + "\1\0\15\67\1\0\15\67\1\0\13\67\1\326\54\67" + + "\1\0\15\67\1\0\15\67\1\0\57\67\1\327\10\67" + + "\1\0\15\67\1\0\15\67\1\0\55\67\1\330\12\67" + + "\1\0\15\67\1\0\15\67\1\0\57\67\1\331\10\67" + + "\1\0\15\67\1\0\15\67\1\0\21\67\1\332\46\67" + + "\1\0\15\67\1\0\15\67\1\0\13\67\1\333\5\67" + + "\1\334\46\67\1\0\15\67\1\0\15\67\1\0\60\67" + + "\1\335\7\67\1\0\15\67\1\0\15\67\1\0\34\67" + + "\1\336\33\67\1\0\15\67\1\0\15\67\1\0\16\67" + + "\1\337\51\67\1\0\15\67\1\0\15\67\1\0\32\67" + + "\1\340\35\67\1\0\15\67\1\0\15\67\1\0\52\67" + + "\1\341\15\67\1\0\15\67\1\0\15\67\1\0\70\67" + + "\1\0\12\67\1\342\2\67\1\0\15\67\1\0\70\67" + + "\1\0\10\67\1\343\4\67\1\0\15\67\1\0\7\67" + + "\27\237\4\67\1\237\6\67\1\344\16\237\1\0\15\237" + + "\1\0\4\67\1\237\3\67\2\237\2\67\11\0\27\345" + + "\4\0\1\345\7\0\16\345\1\240\15\345\1\240\4\0" + + "\1\345\3\0\2\345\2\0\1\67\1\0\70\67\1\0" + + "\2\67\1\317\12\67\1\0\15\67\1\0\7\67\1\213" + + "\60\67\1\0\15\67\1\0\15\67\1\0\15\67\1\346" + + "\52\67\1\0\15\67\1\0\15\67\1\0\54\67\1\347" + + "\13\67\1\0\15\67\1\0\15\67\1\0\7\67\1\350" + + "\60\67\1\0\15\67\1\0\15\67\1\0\13\67\1\351" + + "\54\67\1\0\15\67\1\0\15\67\1\0\13\67\1\352" + + "\54\67\1\0\15\67\1\0\15\67\1\0\52\67\1\353" + + "\15\67\1\0\15\67\1\0\15\67\1\0\16\67\1\354" + + "\51\67\1\0\15\67\1\0\15\67\1\0\21\67\1\355" + + "\46\67\1\0\15\67\1\0\14\67\1\253\1\356\37\253" + + "\1\357\30\253\1\356\15\253\1\356\1\253\1\360\12\253" + + "\5\255\1\0\64\255\1\0\32\255\6\0\2\140\115\0" + + "\6\140\2\257\31\140\1\260\50\140\1\361\12\140\6\0" + + "\2\362\126\0\11\22\1\141\14\22\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\2\22\1\141\23\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\7\22\1\141" + + "\16\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\7\22\1\174\16\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\24\22\1\363\1\22\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\26\22\15\0\1\22\1\364\14\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\2\22\1\365" + + "\23\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\4\22\1\366\21\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\1\367\25\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\11\22" + + "\1\370\14\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\4\22\1\371\21\22" + + "\15\0\16\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\13\0\26\22\15\0\6\22\1\272\7\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\13\0\17\22\1\372\6\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\15\22" + + "\1\141\10\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\45\0\2\310\50\0\1\310" + + "\20\0\26\22\15\0\1\22\1\373\14\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\4\22" + + "\1\174\21\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\1\374\25\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\26\22\15\0\1\375\15\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\26\22" + + "\15\0\1\376\15\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\26\22\15\0\5\22\1\377" + + "\10\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\12\22\1\u0100\13\22\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\117\0" + + "\1\310\20\0\26\204\15\0\16\204\1\0\15\204\2\0" + + "\1\204\1\0\1\204\1\311\1\204\2\0\2\204\7\0" + + "\1\312\120\0\1\312\3\0\1\313\64\0\1\314\15\0" + + "\1\314\14\0\1\67\1\0\54\67\1\u0101\13\67\1\0" + + "\15\67\1\0\15\67\1\0\27\67\1\u0101\40\67\1\0" + + "\15\67\1\0\15\67\1\0\20\67\1\u0102\47\67\1\0" + + "\15\67\1\0\1\u0103\14\67\1\0\13\67\1\u0102\54\67" + + "\1\0\15\67\1\0\15\67\1\0\14\67\1\u0102\53\67" + + "\1\0\15\67\1\0\15\67\1\0\70\67\1\0\15\67" + + "\1\0\1\u0104\14\67\1\0\70\67\1\0\12\67\1\u0105" + + "\2\67\1\0\15\67\1\0\54\67\1\u0106\13\67\1\0" + + "\15\67\1\0\15\67\1\0\57\67\1\u0107\10\67\1\0" + + "\15\67\1\0\15\67\1\0\57\67\1\u0108\10\67\1\0" + + "\15\67\1\0\15\67\1\0\70\67\1\0\2\67\1\u0109" + + "\12\67\1\0\15\67\1\0\60\67\1\u010a\7\67\1\0" + + "\15\67\1\0\15\67\1\0\15\67\1\u010b\52\67\1\0" + + "\15\67\1\0\15\67\1\0\60\67\1\u010c\7\67\1\0" + + "\15\67\1\0\15\67\1\0\66\67\1\u010d\1\67\1\0" + + "\15\67\1\0\15\67\1\0\52\67\1\u010e\15\67\1\0" + + "\15\67\1\0\15\67\1\0\15\67\1\u010f\52\67\1\0" + + "\15\67\1\0\15\67\1\0\24\67\1\u0110\43\67\1\0" + + "\15\67\1\0\15\67\1\0\52\67\1\u0111\15\67\1\0" + + "\15\67\1\0\15\67\1\0\23\67\1\u0112\44\67\1\0" + + "\15\67\1\0\15\67\1\0\57\67\1\u0113\10\67\1\0" + + "\15\67\1\0\15\67\1\0\15\67\1\u0114\52\67\1\0" + + "\15\67\1\0\15\67\1\0\24\67\1\u0115\43\67\1\0" + + "\15\67\1\0\15\67\1\0\7\67\26\u0116\5\67\1\u0116" + + "\7\67\16\u0116\1\0\15\u0116\1\0\4\67\1\u0116\4\67" + + "\1\u0116\2\67\11\0\27\345\4\0\1\345\6\0\1\u0117" + + "\16\345\1\0\15\345\5\0\1\345\3\0\2\345\2\0" + + "\1\67\1\0\57\67\1\u0118\10\67\1\0\15\67\1\0" + + "\15\67\1\0\16\67\1\u0119\51\67\1\0\15\67\1\0" + + "\15\67\1\0\54\67\1\u011a\13\67\1\0\15\67\1\0" + + "\15\67\1\0\57\67\1\u011b\10\67\1\0\15\67\1\0" + + "\15\67\1\0\67\67\1\u011c\1\0\15\67\1\0\15\67" + + "\1\0\16\67\1\u011d\51\67\1\0\15\67\1\0\15\67" + + "\1\0\53\67\1\u011e\14\67\1\0\15\67\1\0\15\67" + + "\1\0\55\67\1\u011f\12\67\1\0\15\67\1\0\14\67" + + "\41\356\1\u0120\50\356\1\u0121\12\356\1\253\1\356\37\253" + + "\1\357\30\253\1\356\15\253\1\356\1\253\1\u0122\12\253" + + "\1\67\1\0\70\67\1\0\15\67\1\0\1\67\1\u0123" + + "\12\67\6\140\2\u0124\31\140\1\260\50\140\1\261\12\140" + + "\11\0\15\22\1\u0125\10\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\1\u0126" + + "\25\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\26\22\15\0\1\151\15\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\13\0\6\22\1\u0127\17\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\4\22" + + "\1\367\21\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\26\22\15\0\1\22" + + "\1\u0128\14\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\13\0\20\22\1\u0129\5\22\15\0\16\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\13\0\26\22\15\0\4\22\1\174\11\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\6\22" + + "\1\u012a\17\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\26\22\15\0\6\22" + + "\1\u012b\7\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\13\0\26\22\15\0\14\22\1\370\1\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\13\0\4\22\1\157\21\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\26\22" + + "\15\0\12\22\1\367\3\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\2\0\1\67\1\0\70\67" + + "\1\u012c\15\67\1\u012c\1\u012d\14\67\1\0\70\67\1\0" + + "\15\67\1\0\1\u0103\14\67\1\0\3\67\1\u012e\64\67" + + "\1\0\15\67\1\0\15\67\1\0\3\67\1\u0103\64\67" + + "\1\0\15\67\1\0\15\67\1\0\13\67\1\u012f\54\67" + + "\1\0\15\67\1\0\15\67\1\0\16\67\1\u0130\51\67" + + "\1\0\15\67\1\0\15\67\1\0\21\67\1\u0131\46\67" + + "\1\0\15\67\1\0\15\67\1\0\55\67\1\u0132\12\67" + + "\1\0\15\67\1\0\15\67\1\0\13\67\1\u0133\54\67" + + "\1\0\15\67\1\0\15\67\1\0\15\67\1\u0134\52\67" + + "\1\0\15\67\1\0\15\67\1\0\67\67\1\u0135\1\0" + + "\15\67\1\0\15\67\1\0\57\67\1\u0136\10\67\1\0" + + "\15\67\1\0\15\67\1\0\13\67\1\u0137\54\67\1\0" + + "\15\67\1\0\15\67\1\0\55\67\1\u0138\12\67\1\0" + + "\15\67\1\0\15\67\1\0\21\67\1\u0112\46\67\1\0" + + "\15\67\1\0\15\67\1\0\70\67\1\0\5\67\1\u0112" + + "\7\67\1\0\15\67\1\0\13\67\1\u0139\54\67\1\0" + + "\15\67\1\0\15\67\1\0\70\67\1\u013a\15\67\1\0" + + "\15\67\1\0\7\67\1\u013b\60\67\1\0\15\67\1\0" + + "\15\67\1\0\10\67\1\u013c\57\67\1\0\15\67\1\0" + + "\15\67\1\0\7\67\26\u0116\1\u013d\4\67\1\u0116\7\67" + + "\16\u0116\1\0\15\u0116\1\0\4\67\1\u0116\4\67\1\u0116" + + "\2\67\11\0\26\u013e\5\0\1\u013e\7\0\16\u013e\1\0" + + "\15\u013e\5\0\1\u013e\4\0\1\u013e\2\0\1\67\1\0" + + "\7\67\1\u013f\60\67\1\0\15\67\1\0\15\67\1\0" + + "\21\67\1\u0140\46\67\1\0\15\67\1\0\15\67\1\0" + + "\15\67\1\u0141\52\67\1\0\15\67\1\0\15\67\1\0" + + "\15\67\1\u0142\52\67\1\0\15\67\1\0\15\67\1\0" + + "\21\67\1\u0143\46\67\1\0\15\67\1\0\15\67\1\0" + + "\54\67\1\u0144\13\67\1\0\15\67\1\0\15\67\1\0" + + "\13\67\1\u0145\54\67\1\0\15\67\1\0\15\67\1\0" + + "\15\67\1\u0146\52\67\1\0\15\67\1\0\14\67\41\356" + + "\1\u0120\50\356\1\u0147\12\356\112\0\1\u0148\12\0\1\253" + + "\1\356\37\253\1\357\30\253\1\356\15\253\1\356\1\253" + + "\1\u0149\12\253\11\0\25\22\1\141\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\6\22\1\u014a\17\22\15\0\16\22\1\0\15\22\2\0" + + "\1\22\1\0\3\22\2\0\2\22\13\0\2\22\1\u014b" + + "\23\22\15\0\16\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\1\157\25\22\15\0\16\22" + + "\1\0\15\22\2\0\1\22\1\0\3\22\2\0\2\22" + + "\13\0\21\22\1\u014c\4\22\15\0\16\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\13\0\7\22" + + "\1\u014d\16\22\15\0\16\22\1\0\15\22\2\0\1\22" + + "\1\0\3\22\2\0\2\22\13\0\7\22\1\367\16\22" + + "\15\0\16\22\1\0\15\22\2\0\1\22\1\0\3\22" + + "\2\0\2\22\74\0\1\u012c\15\0\1\u012c\1\u012d\13\0" + + "\1\u012d\1\0\123\u012d\1\67\1\0\3\67\1\u014e\64\67" + + "\1\0\15\67\1\0\15\67\1\0\70\67\1\u014f\15\67" + + "\1\0\15\67\1\0\70\67\1\u0150\15\67\1\0\15\67" + + "\1\0\63\67\1\u0151\4\67\1\0\15\67\1\0\15\67" + + "\1\0\54\67\1\u0152\13\67\1\0\15\67\1\0\15\67" + + "\1\0\20\67\1\u0153\47\67\1\0\15\67\1\0\15\67" + + "\1\0\53\67\1\u0154\14\67\1\0\15\67\1\0\15\67" + + "\1\0\7\67\1\u0155\60\67\1\0\15\67\1\0\15\67" + + "\1\0\54\67\1\u0156\13\67\1\0\15\67\1\0\15\67" + + "\1\0\16\67\1\u0157\51\67\1\0\15\67\1\0\15\67" + + "\1\0\13\67\1\u0158\54\67\1\0\15\67\1\0\15\67" + + "\1\0\57\67\1\u0159\10\67\1\0\15\67\1\0\14\67" + + "\101\0\1\u015a\23\0\1\67\1\0\13\67\1\u015b\54\67" + + "\1\0\15\67\1\0\15\67\1\0\31\67\1\u015c\36\67" + + "\1\0\15\67\1\0\15\67\1\0\7\67\26\u015d\5\67" + + "\1\u0116\7\67\16\u015d\1\0\15\u015d\1\0\4\67\1\u0116" + + "\4\67\1\u015d\2\67\11\0\26\u013e\1\u015e\4\0\1\u013e" + + "\7\0\16\u013e\1\0\15\u013e\5\0\1\u013e\4\0\1\u013e" + + "\2\0\1\67\1\0\54\67\1\u015f\13\67\1\0\15\67" + + "\1\0\15\67\1\0\60\67\1\u0160\7\67\1\0\15\67" + + "\1\0\15\67\1\0\16\67\1\u0161\51\67\1\0\15\67" + + "\1\0\15\67\1\0\16\67\1\u0162\51\67\1\0\15\67" + + "\1\0\15\67\1\0\16\67\1\u0163\51\67\1\0\15\67" + + "\1\0\15\67\1\0\70\67\1\u0164\15\67\1\0\15\67" + + "\1\0\16\67\1\u0165\51\67\1\0\15\67\1\0\15\67" + + "\1\0\20\67\1\u0166\47\67\1\0\15\67\1\0\14\67" + + "\41\356\1\u0120\50\356\1\u0167\12\356\11\0\26\22\15\0" + + "\2\22\1\u0168\13\22\1\0\15\22\2\0\1\22\1\0" + + "\3\22\2\0\2\22\13\0\22\22\1\141\3\22\15\0" + + "\16\22\1\0\15\22\2\0\1\22\1\0\3\22\2\0" + + "\2\22\13\0\26\22\15\0\1\370\15\22\1\0\15\22" + + "\2\0\1\22\1\0\3\22\2\0\2\22\2\0\1\u0169" + + "\1\0\4\u0169\2\67\62\u0169\1\0\15\u0169\1\0\2\u0169" + + "\1\67\4\u0169\1\67\4\u0169\24\0\1\u016a\132\0\1\u016b" + + "\72\0\1\67\1\0\70\67\1\u016c\15\67\1\0\15\67" + + "\1\0\16\67\1\u016d\51\67\1\0\15\67\1\0\15\67" + + "\1\0\7\67\1\u016e\60\67\1\0\15\67\1\0\15\67" + + "\1\0\70\67\1\u016f\15\67\1\0\15\67\1\0\13\67" + + "\1\u0170\54\67\1\0\15\67\1\0\15\67\1\0\7\67" + + "\1\u0171\60\67\1\0\15\67\1\0\15\67\1\0\7\67" + + "\1\u0172\60\67\1\0\15\67\1\0\15\67\1\0\70\67" + + "\1\u0173\15\67\1\0\15\67\1\0\70\67\1\u0174\15\67" + + "\1\0\14\67\17\0\1\u0175\6\0\1\u0176\76\0\1\67" + + "\1\0\54\67\1\u0112\13\67\1\0\15\67\1\0\15\67" + + "\1\0\27\67\1\u0112\40\67\1\0\15\67\1\0\15\67" + + "\1\0\7\67\26\u0177\1\u013d\4\67\1\u0116\7\67\16\u0177" + + "\1\0\15\u0177\1\0\4\67\1\u0116\4\67\1\u0177\2\67" + + "\11\0\26\u0178\5\0\1\u013e\7\0\16\u0178\1\0\15\u0178" + + "\5\0\1\u013e\4\0\1\u0178\2\0\1\67\1\0\70\67" + + "\1\0\15\67\1\0\1\u0179\14\67\1\0\55\67\1\u017a" + + "\12\67\1\0\15\67\1\0\15\67\1\0\13\67\1\u017b" + + "\54\67\1\0\15\67\1\0\15\67\1\0\13\67\1\u017c" + + "\54\67\1\0\15\67\1\0\15\67\1\0\55\67\1\u017d" + + "\12\67\1\0\15\67\1\0\14\67\102\0\1\u017e\22\0" + + "\1\67\1\0\7\67\1\u017f\60\67\1\0\15\67\1\0" + + "\15\67\1\0\57\67\1\u0180\10\67\1\0\15\67\1\0" + + "\14\67\11\0\7\22\1\u0181\16\22\15\0\16\22\1\0" + + "\15\22\2\0\1\22\1\0\3\22\2\0\2\22\13\0" + + "\1\u0182\1\u0183\135\0\1\u0184\54\0\1\u0185\57\0\1\u0186" + + "\71\0\1\67\1\0\70\67\1\u0187\15\67\1\0\15\67" + + "\1\0\60\67\1\u0188\7\67\1\0\15\67\1\0\14\67" + + "\35\0\1\u0189\67\0\1\67\1\0\70\67\1\u018a\15\67" + + "\1\0\15\67\1\0\7\67\1\u018b\60\67\1\0\15\67" + + "\1\0\15\67\1\0\70\67\1\u018c\15\67\1\0\14\67" + + "\103\0\1\u018d\123\0\1\u018e\127\0\1\u018f\122\0\1\u0190" + + "\21\0\1\67\1\0\7\67\26\u0191\1\u013d\4\67\1\u0116" + + "\3\67\1\u0192\3\67\16\u0191\1\u0193\15\u0191\1\u0193\4\67" + + "\1\u0116\4\67\1\u0191\2\67\11\0\26\u0194\1\u015e\4\0" + + "\1\u013e\7\0\16\u0194\1\0\15\u0194\5\0\1\u013e\4\0" + + "\1\u0194\2\0\1\67\1\0\7\67\27\u0195\4\67\1\u0195" + + "\7\67\16\u0195\1\u0196\15\u0195\1\u0196\4\67\1\u0195\3\67" + + "\2\u0195\3\67\1\0\70\67\1\u0197\15\67\1\0\15\67" + + "\1\0\70\67\1\u0198\15\67\1\0\15\67\1\0\70\67" + + "\1\u0199\15\67\1\0\15\67\1\0\60\67\1\u019a\7\67" + + "\1\0\15\67\1\0\14\67\31\0\1\u019b\24\0\1\u019c" + + "\46\0\1\67\1\0\70\67\1\u019d\15\67\1\0\15\67" + + "\1\0\21\67\1\u019e\46\67\1\0\15\67\1\0\14\67" + + "\15\0\1\u019f\142\0\1\u01a0\153\0\1\u01a1\100\0\1\u01a2" + + "\106\0\1\u01a3\131\0\1\u01a4\77\0\1\67\1\0\13\67" + + "\1\u01a5\54\67\1\0\15\67\1\0\14\67\15\0\1\u01a6" + + "\15\0\1\u01a7\126\0\1\u01a8\67\0\1\67\1\0\13\67" + + "\1\u01a9\54\67\1\0\15\67\1\0\14\67\35\0\1\u01aa" + + "\120\0\1\u01ab\24\0\1\u01ac\122\0\1\u01ad\22\0\1\u01ae" + + "\45\0\1\u01af\177\0\1\u01b0\31\0\1\67\1\0\7\67" + + "\26\u01b1\1\u013d\4\67\1\u0116\3\67\1\u0192\3\67\16\u01b1" + + "\1\u0193\15\u01b1\1\u0193\4\67\1\u0116\4\67\1\u01b1\2\67" + + "\50\0\1\u01b2\21\0\1\u0193\15\0\1\u0193\25\0\26\u01b3" + + "\1\u015e\4\0\1\u013e\3\0\1\u01b2\3\0\16\u01b3\1\u0193" + + "\15\u01b3\1\u0193\4\0\1\u013e\4\0\1\u01b3\2\0\1\67" + + "\1\0\7\67\27\u0195\4\67\1\u0195\6\67\1\u01b4\16\u0195" + + "\1\0\15\u0195\1\0\4\67\1\u0195\3\67\2\u0195\2\67" + + "\11\0\27\u01b5\4\0\1\u01b5\7\0\16\u01b5\1\u0196\15\u01b5" + + "\1\u0196\4\0\1\u01b5\3\0\2\u01b5\32\0\1\u01b6\127\0" + + "\1\u01b7\116\0\1\u01b8\77\0\1\67\1\0\13\67\1\u01b9" + + "\54\67\1\0\15\67\1\0\14\67\14\0\1\u01ba\123\0" + + "\1\u01bb\136\0\1\u01bc\77\0\1\67\1\0\70\67\1\0" + + "\2\67\1\u01bd\12\67\1\0\14\67\15\0\1\u01be\142\0" + + "\1\u01bf\146\0\1\u01c0\74\0\1\u01c1\110\0\1\u01c2\171\0" + + "\1\u01c3\46\0\1\67\1\0\70\67\1\u01c4\15\67\1\0" + + "\14\67\61\0\1\u01c5\141\0\1\u01c6\43\0\1\u01c7\15\0" + + "\1\u01c8\71\0\1\67\1\0\70\67\1\u01c9\15\67\1\0" + + "\14\67\23\0\1\u01ca\54\0\1\u01cb\56\0\1\u01cc\162\0" + + "\1\u01cd\115\0\1\u01ce\141\0\1\u01cf\45\0\1\u019f\133\0" + + "\1\u01a0\76\0\1\67\1\0\7\67\26\u01d0\1\u013d\4\67" + + "\1\u0116\3\67\1\u0192\3\67\16\u01d0\1\u0193\15\u01d0\1\u0193" + + "\4\67\1\u0116\4\67\1\u01d0\2\67\11\0\26\u01d1\1\u015e" + + "\4\0\1\u013e\3\0\1\u01b2\3\0\16\u01d1\1\u0193\15\u01d1" + + "\1\u0193\4\0\1\u013e\4\0\1\u01d1\2\0\1\67\1\0" + + "\7\67\26\u01d2\5\67\1\u01d2\7\67\16\u01d2\1\0\15\u01d2" + + "\1\0\4\67\1\u01d2\4\67\1\u01d2\2\67\11\0\27\u01b5" + + "\4\0\1\u01b5\6\0\1\u01d3\16\u01b5\1\0\15\u01b5\5\0" + + "\1\u01b5\3\0\2\u01b5\60\0\1\u01d4\127\0\1\u01d5\14\0" + + "\1\u01d6\51\0\1\u01d7\54\0\1\u01d8\24\0\1\67\1\0" + + "\70\67\1\u01d9\15\67\1\0\14\67\36\0\1\u01da\150\0" + + "\1\u01db\73\0\1\u01dc\24\0\1\u01dd\46\0\1\67\1\0" + + "\70\67\1\u01de\15\67\1\0\14\67\62\0\1\u01df\100\0" + + "\1\u01df\146\0\1\u01e0\74\0\1\u01e1\111\0\1\u01e2\44\0" + + "\1\u01e3\120\0\1\u01e4\144\0\1\u01e5\51\0\1\u01e6\201\0" + + "\1\u01e7\44\0\1\u01e8\177\0\1\u01e9\61\0\1\u01ea\171\0" + + "\1\u01eb\133\0\1\u01ec\53\0\1\u01ed\106\0\1\u01ee\126\0" + + "\1\u01ef\133\0\1\u01f0\76\0\1\67\1\0\7\67\26\u0116" + + "\1\u013d\4\67\1\u0116\3\67\1\u0192\3\67\16\u0116\1\u0193" + + "\15\u0116\1\u0193\4\67\1\u0116\4\67\1\u0116\2\67\11\0" + + "\26\u01f1\1\u015e\4\0\1\u013e\3\0\1\u01b2\3\0\16\u01f1" + + "\1\u0193\15\u01f1\1\u0193\4\0\1\u013e\4\0\1\u01f1\2\0" + + "\1\67\1\0\7\67\26\u01d2\1\u01f2\4\67\1\u01d2\7\67" + + "\16\u01d2\1\0\15\u01d2\1\0\4\67\1\u01d2\4\67\1\u01d2" + + "\2\67\11\0\26\u01f3\5\0\1\u01f3\7\0\16\u01f3\1\0" + + "\15\u01f3\5\0\1\u01f3\4\0\1\u01f3\15\0\1\u01f4\130\0" + + "\1\u01f5\133\0\1\u01f6\160\0\1\u01f7\100\0\1\u01f8\116\0" + + "\1\u01f9\127\0\1\u01fa\106\0\1\u01fb\206\0\1\u01fc\101\0" + + "\1\u01fd\62\0\1\u01fe\127\0\1\u01ff\142\0\1\u0200\153\0" + + "\1\u0201\57\0\1\u0202\125\0\1\u019f\123\0\1\u0203\15\0" + + "\1\u0204\161\0\1\u0205\66\0\1\u0206\111\0\1\u0207\133\0" + + "\1\u0208\113\0\1\u0209\15\0\1\u020a\110\0\1\u020b\133\0" + + "\1\u020c\172\0\1\u01df\51\0\1\u01df\126\0\1\u020d\201\0" + + "\1\u020e\35\0\26\u013e\1\u015e\4\0\1\u013e\3\0\1\u01b2" + + "\3\0\16\u013e\1\u0193\15\u013e\1\u0193\4\0\1\u013e\4\0" + + "\1\u013e\2\0\1\67\1\0\7\67\26\u020f\5\67\1\u01d2" + + "\7\67\16\u020f\1\0\15\u020f\1\0\4\67\1\u01d2\4\67" + + "\1\u020f\2\67\11\0\26\u01f3\1\u0210\4\0\1\u01f3\7\0" + + "\16\u01f3\1\0\15\u01f3\5\0\1\u01f3\4\0\1\u01f3\24\0" + + "\1\u0211\125\0\1\u0212\201\0\1\u0213\44\0\1\u0214\177\0" + + "\1\u0215\46\0\1\u0216\15\0\1\u0217\103\0\1\u01df\123\0" + + "\1\u01df\217\0\1\u0218\115\0\1\u0219\65\0\1\u021a\23\0" + + "\1\u021b\53\0\1\u021c\125\0\1\u021d\130\0\1\u021e\124\0" + + "\1\u021f\165\0\1\u0220\102\0\1\u0221\112\0\1\u0222\201\0" + + "\1\u0223\45\0\1\u01db\177\0\1\u01da\105\0\1\u0224\74\0" + + "\1\u0225\156\0\1\u01df\102\0\1\u01df\144\0\1\u0226\74\0" + + "\1\u0227\77\0\1\67\1\0\7\67\26\u0228\1\u01f2\4\67" + + "\1\u01d2\7\67\16\u0228\1\0\15\u0228\1\0\4\67\1\u01d2" + + "\4\67\1\u0228\2\67\11\0\26\u0229\5\0\1\u01f3\7\0" + + "\16\u0229\1\0\15\u0229\5\0\1\u01f3\4\0\1\u0229\13\0" + + "\1\u022a\135\0\1\u01df\126\0\1\u01df\117\0\1\u0212\133\0" + + "\1\u0213\160\0\1\u022b\100\0\1\u022c\121\0\1\u022d\106\0" + + "\1\u022e\206\0\1\u022f\101\0\1\u0230\61\0\1\u0231\125\0" + + "\1\u0232\174\0\1\u0233\124\0\1\u0234\124\0\1\u0235\100\0" + + "\1\u0236\150\0\1\u0237\100\0\1\u0238\155\0\1\u0239\143\0" + + "\1\u023a\76\0\1\u0212\74\0\1\u0213\74\0\1\67\1\0" + + "\7\67\26\u023b\1\u01f2\4\67\1\u01d2\7\67\16\u023b\1\u023c" + + "\15\u023b\1\u023c\4\67\1\u01d2\4\67\1\u023b\2\67\11\0" + + "\26\u023d\1\u0210\4\0\1\u01f3\7\0\16\u023d\1\0\15\u023d" + + "\5\0\1\u01f3\4\0\1\u023d\25\0\1\u023e\120\0\1\u023f" + + "\133\0\1\u0240\134\0\1\u01fa\150\0\1\u01fb\143\0\1\u0241" + + "\110\0\1\u0242\115\0\1\u01df\77\0\1\u01df\112\0\1\u0243" + + "\124\0\1\u0244\161\0\1\u01df\147\0\1\u01df\107\0\1\u0245" + + "\100\0\1\u0246\142\0\1\u01db\147\0\1\u01da\25\0\1\67" + + "\1\0\7\67\26\u0247\1\u01f2\4\67\1\u01d2\7\67\16\u0247" + + "\1\u023c\15\u0247\1\u023c\4\67\1\u01d2\4\67\1\u0247\2\67" + + "\72\0\1\u023c\15\0\1\u023c\25\0\26\u0248\1\u0210\4\0" + + "\1\u01f3\7\0\16\u0248\1\u023c\15\u0248\1\u023c\4\0\1\u01f3" + + "\4\0\1\u0248\61\0\1\u0249\67\0\1\u024a\126\0\1\u024b" + + "\207\0\1\u024c\103\0\1\u024d\60\0\1\u024e\124\0\1\u024f" + + "\117\0\1\u01df\142\0\1\u01df\71\0\1\67\1\0\7\67" + + "\26\u0250\1\u01f2\4\67\1\u01d2\7\67\16\u0250\1\u023c\15\u0250" + + "\1\u023c\4\67\1\u01d2\4\67\1\u0250\2\67\11\0\26\u0251" + + "\1\u0210\4\0\1\u01f3\7\0\16\u0251\1\u023c\15\u0251\1\u023c" + + "\4\0\1\u01f3\4\0\1\u0251\13\0\1\u019f\135\0\1\u0245" + + "\126\0\1\u0246\126\0\1\u0252\115\0\1\u0253\122\0\1\u0254" + + "\124\0\1\u0255\107\0\1\67\1\0\7\67\26\u01d2\1\u01f2" + + "\4\67\1\u01d2\7\67\16\u01d2\1\u023c\15\u01d2\1\u023c\4\67" + + "\1\u01d2\4\67\1\u01d2\2\67\11\0\26\u0256\1\u0210\4\0" + + "\1\u01f3\7\0\16\u0256\1\u023c\15\u0256\1\u023c\4\0\1\u01f3" + + "\4\0\1\u0256\75\0\1\u01df\51\0\1\u01df\126\0\1\137" + + "\113\0\26\u01f3\1\u0210\4\0\1\u01f3\7\0\16\u01f3\1\u023c" + + "\15\u01f3\1\u023c\4\0\1\u01f3\4\0\1\u01f3\2\0"; + + private static int [] zzUnpackTrans() { + int [] result = new int[46920]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do { + result[j++] = value; + } while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code> + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\1\0\1\1\3\0\1\1\1\0\3\11\46\1\1\11" + + "\2\1\2\11\2\1\1\11\17\1\1\11\4\1\1\11" + + "\2\1\1\11\2\1\2\11\4\1\2\11\2\1\3\11" + + "\1\0\27\1\2\0\6\1\1\0\1\1\2\0\2\1" + + "\3\0\27\1\1\0\13\1\1\0\2\1\3\0\30\1" + + "\1\11\2\0\30\1\1\0\10\1\1\0\2\1\1\0" + + "\1\11\44\1\1\0\10\1\2\0\12\1\1\0\15\1" + + "\1\0\3\1\1\0\10\1\1\0\1\11\6\1\2\0" + + "\11\1\1\0\3\1\1\0\5\1\1\0\5\1\3\0" + + "\2\1\1\0\3\1\4\0\1\1\1\0\5\1\1\0" + + "\3\1\6\0\1\1\2\0\1\1\5\0\2\1\2\0" + + "\1\1\4\0\1\1\3\0\1\1\6\0\1\1\3\0" + + "\1\1\7\0\1\1\1\11\1\0\1\1\4\0\1\1" + + "\3\0\1\1\22\0\1\1\1\0\1\1\14\0\1\11" + + "\22\0\1\1\34\0\1\1\30\0\1\1\22\0\3\1" + + "\11\0\2\1\7\0\2\1\2\0\3\1"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[598]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do { + result[j++] = value; + } while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + public int start; + public int end; + public int beginString; + public static Set<String> commands = new HashSet<String>(); + public static Set<String> macros = new HashSet<String>(); + public static Set<String> variables = new HashSet<String>(); + public Set<String> infile; + + private ScilabDocument doc; + private boolean transposable; + private Element elem; + private boolean breakstring; + + static { + // For SciNotes colors in preferences + commands.add("cos"); + macros.add("cosh"); + } + + public ScilabLexer(ScilabDocument doc) { + this(doc, true); + } + + public ScilabLexer(ScilabDocument doc, boolean update) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + this.infile = doc.getFunctionsInDoc(); + if (update) { + update(); + } + } + + public static void update() { + if (ScilabCommonsUtils.isScilabThread()) { + String[] vars = ScilabKeywords.GetVariablesName(); + String[] funs = ScilabKeywords.GetFunctionsName(); + String[] macs = ScilabKeywords.GetMacrosName(); + variables.clear(); + commands.clear(); + macros.clear(); + if (vars != null) { + variables.addAll(Arrays.asList(vars)); + } + if (funs != null) { + commands.addAll(Arrays.asList(funs)); + } + if (macs != null) { + macros.addAll(Arrays.asList(macs)); + } + } + } + + public void setRange(int p0, int p1) { + start = p0; + end = p1; + transposable = false; + breakstring = false; + yyreset(new ScilabDocumentReader(doc, p0, p1)); + int currentLine = elem.getElementIndex(start); + if (currentLine != 0 && ((ScilabDocument.ScilabLeafElement) elem.getElement(currentLine - 1)).isBrokenString()) { + yybegin(QSTRING); + } + } + + public int yychar() { + return yychar; + } + + public int scan() throws IOException { + int ret = yylex(); + if (start + yychar + yylength() == end - 1) { + ((ScilabDocument.ScilabLeafElement) elem.getElement(elem.getElementIndex(start))).setBrokenString(breakstring); + breakstring = false; + } + return ret; + } + + public int getKeyword(int pos, boolean strict) { + Element line = elem.getElement(elem.getElementIndex(pos)); + int end = line.getEndOffset(); + int tok = -1; + start = line.getStartOffset(); + int startL = start; + int s = -1; + + try { + yyreset(new ScilabDocumentReader(doc, start, end)); + if (!strict) { + pos++; + } + + while (startL < pos && (s != startL || yystate() == BREAKSTRING)) { + s = startL; + tok = yylex(); + startL = start + yychar + yylength(); + } + + return tok; + } catch (IOException e) { + return ScilabLexerConstants.DEFAULT; + } + } + + public static ScilabTokens getScilabTokens(String str) { + ScilabDocument doc = new ScilabDocument(false); + try { + doc.insertString(0, str, null); + } catch (BadLocationException e) { } + return getScilabTokens(doc); + } + + public static ScilabTokens getScilabTokens(ScilabDocument doc) { + ScilabLexer lexer = new ScilabLexer(doc); + lexer.yyreset(new ScilabDocumentReader(doc, 0, doc.getLength())); + ScilabTokens tokens = new ScilabTokens(); + int tok = -1; + try { + while (tok != ScilabLexerConstants.EOF) { + tok = lexer.yylex(); + tokens.add(tok, lexer.yychar + lexer.yylength()); + } + } catch (IOException e) { } + + return tokens; + } + + public static class ScilabTokens { + private List<Integer> tokenType = new ArrayList<Integer>(); + private List<Integer> tokenPos = new ArrayList<Integer>(); + + ScilabTokens() { } + + void add(final int type, final int pos) { + tokenType.add(type); + tokenPos.add(pos); + } + + public final List<Integer> getTokenType() { + return tokenType; + } + + public final List<Integer> getTokenPos() { + return tokenPos; + } + } + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + public ScilabLexer(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public ScilabLexer(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 210) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do { + map[j++] = value; + } while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return <code>false</code>, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead - zzStartRead); + + /* translate stored positions */ + zzEndRead -= zzStartRead; + zzCurrentPos -= zzStartRead; + zzMarkedPos -= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos * 2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length - zzEndRead); + + if (numRead > 0) { + zzEndRead += numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) { + zzReader.close(); + } + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * <b>cannot</b> be reused (internal buffer is discarded and lost). + * Lexical state is set to <tt>ZZ_INITIAL</tt>. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos - zzStartRead ); + } + + + /** + * Returns the character at position <tt>pos</tt> from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead + pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos - zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) { + zzScanError(ZZ_PUSHBACK_2BIG); + } + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public int yylex() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar += zzMarkedPosL - zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) { + zzInput = zzBufferL[zzCurrentPosL++]; + } else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) { + break zzForAction; + } + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) { + break zzForAction; + } + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 34: { + transposable = false; + return ScilabLexerConstants.SKEYWORD; + } + case 46: + break; + case 1: { + return ScilabLexerConstants.STRING; + } + case 47: + break; + case 28: { + return ScilabLexerConstants.WHITE; + } + case 48: + break; + case 42: { + return ScilabLexerConstants.TODO; + } + case 49: + break; + case 31: { + return ScilabLexerConstants.ERROR; + } + case 50: + break; + case 2: { + transposable = false; + return ScilabLexerConstants.DEFAULT; + } + case 51: + break; + case 3: { + transposable = false; + return ScilabLexerConstants.OPENCLOSE; + } + case 52: + break; + case 38: { + transposable = false; + return ScilabLexerConstants.ELSEIF; + } + case 53: + break; + case 26: { + yybegin(COMMANDSWHITE); + return ScilabLexerConstants.WHITE; + } + case 54: + break; + case 43: { + return ScilabLexerConstants.URL; + } + case 55: + break; + case 12: { + transposable = false; + return ScilabLexerConstants.SPECIAL; + } + case 56: + break; + case 39: { + transposable = false; + return ScilabLexerConstants.CKEYWORD; + } + case 57: + break; + case 21: { + return ScilabLexerConstants.TAB_COMMENT; + } + case 58: + break; + case 32: { + transposable = true; + return ScilabLexerConstants.CONSTANTES; + } + case 59: + break; + case 11: { + transposable = false; + return ScilabLexerConstants.TAB; + } + case 60: + break; + case 17: { + return ScilabLexerConstants.TAB_STRING; + } + case 61: + break; + case 41: { + return ScilabLexerConstants.LATEX; + } + case 62: + break; + case 23: { + transposable = true; + return ScilabLexerConstants.FIELD; + } + case 63: + break; + case 14: { + return ScilabLexerConstants.DEFAULT; + } + case 64: + break; + case 36: { + yypushback(yylength()); + yybegin(BREAKSTRING); + transposable = false; + return ScilabLexerConstants.STRING; + } + case 65: + break; + case 44: { + transposable = false; + return ScilabLexerConstants.FKEYWORD; + } + case 66: + break; + case 7: { + transposable = false; + beginString = zzStartRead; + yybegin(QSTRING); + return ScilabLexerConstants.STRING; + } + case 67: + break; + case 35: { + breakstring = true; + return ScilabLexerConstants.SPECIAL; + } + case 68: + break; + case 20: { + return ScilabLexerConstants.WHITE_COMMENT; + } + case 69: + break; + case 37: { + return ScilabLexerConstants.LATEXINSTRING; + } + case 70: + break; + case 25: { + yypushback(yylength()); + yybegin(YYINITIAL); + } + case 71: + break; + case 9: { + transposable = false; + yybegin(FIELD); + return ScilabLexerConstants.OPERATOR; + } + case 72: + break; + case 33: { + transposable = false; + return ScilabLexerConstants.OSKEYWORD; + } + case 73: + break; + case 45: { + return ScilabLexerConstants.MAIL; + } + case 74: + break; + case 13: { + transposable = true; + return ScilabLexerConstants.NUMBER; + } + case 75: + break; + case 40: { + return ScilabLexerConstants.AUTHORS; + } + case 76: + break; + case 16: { + return ScilabLexerConstants.WHITE_STRING; + } + case 77: + break; + case 22: { + yypushback(1); + yybegin(YYINITIAL); + } + case 78: + break; + case 8: { + transposable = true; + String str = yytext(); + if (commands.contains(str)) { + yybegin(COMMANDS); + return ScilabLexerConstants.COMMANDS; + } else if (macros.contains(str)) { + yybegin(COMMANDS); + return ScilabLexerConstants.MACROS; + } else if (infile.contains(str)) { + yybegin(COMMANDS); + return ScilabLexerConstants.MACROINFILE; + } else { + List<String>[] arr = doc.getInOutArgs(start + yychar); + if (arr != null && (arr[0].contains(str) || arr[1].contains(str))) { + return ScilabLexerConstants.INPUTOUTPUTARGS; + } else if (variables.contains(str)) { + return ScilabLexerConstants.VARIABLES; + } + } + return ScilabLexerConstants.ID; + } + case 79: + break; + case 6: { + if (transposable) { + return ScilabLexerConstants.TRANSP; + } else { + beginString = zzStartRead; + yybegin(QSTRING); + return ScilabLexerConstants.STRING; + } + } + case 80: + break; + case 18: { + return ScilabLexerConstants.COMMENT; + } + case 81: + break; + case 30: { + transposable = false; + yypushback(2); + yybegin(COMMENT); + } + case 82: + break; + case 19: { + yybegin(YYINITIAL); + return ScilabLexerConstants.DEFAULT; + } + case 83: + break; + case 27: { + yybegin(COMMANDSWHITE); + return ScilabLexerConstants.TAB; + } + case 84: + break; + case 4: { + transposable = true; + return ScilabLexerConstants.OPENCLOSE; + } + case 85: + break; + case 15: { + transposable = false; + yybegin(YYINITIAL); + return ScilabLexerConstants.STRING; + } + case 86: + break; + case 10: { + transposable = false; + return ScilabLexerConstants.WHITE; + } + case 87: + break; + case 5: { + transposable = false; + return ScilabLexerConstants.OPERATOR; + } + case 88: + break; + case 29: { + return ScilabLexerConstants.TAB; + } + case 89: + break; + case 24: { + } + case 90: + break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + { + return ScilabLexerConstants.EOF; + } + } else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabLexerConstants.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabLexerConstants.java new file mode 100755 index 000000000..e37035f10 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabLexerConstants.java @@ -0,0 +1,380 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + +/** + * This class contains constants used in the lexer + * @author Calixte DENIZET + */ +public class ScilabLexerConstants { + + /** + * Number of known tokens + */ + public static final int NUMBEROFTOKENS = 36; + + /** + * DEFAULT : tokens which are not recognized + */ + public static final int DEFAULT = 0; + + /** + * OPERATOR : tokens like '+', '-', ... + */ + public static final int OPERATOR = 1; + + /** + * SKEYWORD : Structure keywords like 'then', 'else' or 'catch' ... + */ + public static final int SKEYWORD = 2; + + /** + * OSKEYWORD : Structure keywords like 'if', 'for' or 'while' + */ + public static final int OSKEYWORD = 3; + + /** + * CKEYWORD : Control keywords like 'abort', 'break' or 'return' + */ + public static final int CKEYWORD = 4; + + /** + * CONSTANTES : Constantes like '%pi' or '%T' + */ + public static final int CONSTANTES = 5; + + /** + * ID : Identifiers like 'myvar' or 'myfun' + */ + public static final int ID = 6; + + /** + * NUMBER : I don't know ;) + */ + public static final int NUMBER = 7; + + /** + * SPECIAL : Special keywords like '$', ':' or '...' + */ + public static final int SPECIAL = 8; + + /** + * DOT : the dot in a field context, e.g. 'object.myfield' + */ + public static final int DOT = 9; + + /** + * TRANSP : just the transpose operator + */ + public static final int TRANSP = 10; + + /** + * OPENCLOSE : an opening char like '(', '[', '{' or ')' + */ + public static final int OPENCLOSE = 11; + + /** + * STRING : "bla bla bla" or 'bli bli bli' (or fucking exotic way to write a string) + */ + public static final int STRING = 12; + + /** + * COMMENT : Comments like // An interesting commentary + */ + public static final int COMMENT = 13; + + /** + * FKEYWORD : For keywords 'function' and 'endfunction' + */ + public static final int FKEYWORD = 14; + + /** + * COMMANDS : Built-in functions in Scilab + */ + public static final int COMMANDS = 15; + + /** + * MACROS : Macros in Scilab + */ + public static final int MACROS = 16; + + /** + * MACROINFILE : Macros in Scilab + */ + public static final int MACROINFILE = 17; + + /** + * FIELD : Field of an object, e.g. myobject.myfield + */ + public static final int FIELD = 18; + + /** + * AUTHORS : Authors in Scilab + */ + public static final int AUTHORS = 19; + + /** + * URL : http://... + */ + public static final int URL = 20; + + /** + * MAIL : <pierre.marechal@scilab.org> + */ + public static final int MAIL = 21; + + /** + * WHITE : A white char ' ' + */ + public static final int WHITE = 22; + + /** + * TAB : A tabulation '\t' + */ + public static final int TAB = 23; + + /** + * LATEX : $\frac\pi\alpha$ + */ + public static final int LATEX = 24; + + /** + * LATEXINSTRING : $\frac\pi\alpha$ + */ + public static final int LATEXINSTRING = 25; + + /** + * VARIABLES : A variable in Scilab + */ + public static final int VARIABLES = 26; + + /** + * INPUTOUTPUTARGS : A variable as arg in function declaration + */ + public static final int INPUTOUTPUTARGS = 27; + + /** + * WHITE_COMMENT : A white char ' ' in comments + */ + public static final int WHITE_COMMENT = 28; + + /** + * TAB_COMMENT : A tabulation '\t' in comments + */ + public static final int TAB_COMMENT = 29; + + /** + * WHITE_STRING : A white char ' ' in strings + */ + public static final int WHITE_STRING = 30; + + /** + * TAB_STRING : A tabulation '\t' in strings + */ + public static final int TAB_STRING = 31; + + /** + * ELSEIF : elseif keyword + */ + public static final int ELSEIF = 32; + + /** + * ERROR : a syntax error for example + */ + public static final int ERROR = 33; + + /** + * EOF : End Of File + */ + public static final int TODO = 34; + + /** + * EOF : End Of File + */ + public static final int EOF = 35; + + /** + * TOKENS : A Map which contains the names of keywords (useful in scinotesConfiguration.xml) + */ + public static final Map<String, Integer> TOKENS = new HashMap<String, Integer>(28); + + private static Map<Integer, String> idTokens; + + static { + TOKENS.put("Default", DEFAULT); + TOKENS.put("Special", SPECIAL); + TOKENS.put("Operator", OPERATOR); + TOKENS.put("Primitive", COMMANDS); + TOKENS.put("Macro", MACROS); + TOKENS.put("MacroInFile", MACROINFILE); + TOKENS.put("String", STRING); + TOKENS.put("ExternalVariable", VARIABLES); + TOKENS.put("InputOutputArgs", INPUTOUTPUTARGS); + TOKENS.put("Identifier", ID); + TOKENS.put("Comment", COMMENT); + TOKENS.put("Field", FIELD); + TOKENS.put("FunctionKwd", FKEYWORD); + TOKENS.put("Url", URL); + TOKENS.put("Mail", MAIL); + TOKENS.put("Number", NUMBER); + TOKENS.put("Control", CKEYWORD); + TOKENS.put("Structure", SKEYWORD); + TOKENS.put("Constantes", CONSTANTES); + TOKENS.put("White", WHITE); + TOKENS.put("WhiteInComment", WHITE_COMMENT); + TOKENS.put("WhiteInString", WHITE_STRING); + TOKENS.put("Tabulation", TAB); + TOKENS.put("TabulationInComment", TAB_COMMENT); + TOKENS.put("LaTeXInComment", LATEX); + TOKENS.put("LaTeXInString", LATEXINSTRING); + TOKENS.put("TabulationInString", TAB_STRING); + TOKENS.put("OpenClose", OPENCLOSE); + TOKENS.put("Todo", TODO); + } + + /** + * getStringRep + * @param id the type of a token + * @return the string representation in config file of this token + */ + public final static String getStringRep(int id) { + if (idTokens == null) { + idTokens = new HashMap<Integer, String>(TOKENS.size()); + Iterator<String> iterator = TOKENS.keySet().iterator(); + while (iterator.hasNext()) { + String key = iterator.next(); + idTokens.put(TOKENS.get(key), key); + } + } + + String rep = idTokens.get(id); + if (rep != null) { + return rep; + } + if (id == OSKEYWORD || id == ELSEIF) { + return "Structure"; + } + return "Default"; + } + + /** + * Have we a LaTeX string ? + * @param type the type of the keyword + * @return true if the keyword is a LaTeX string + */ + public static final boolean isLaTeX(final int type) { + return type == LATEX || type == LATEXINSTRING; + } + + /** + * Have we a piece of a Scilab string ? + * @param type the type of the keyword + * @return true if the keyword is a piece of Scilab string + */ + public static final boolean isString(final int type) { + return type == STRING || type == WHITE_STRING || type == TAB_STRING; + } + + /** + * Have we a LaTeX string ? + * @param type the type of the keyword + * @return true if the keyword is a LaTeX string + */ + public static final boolean isComment(final int type) { + return type == COMMENT || type == AUTHORS || type == URL || type == MAIL || type == LATEX || type == WHITE_COMMENT || type == TAB_COMMENT || type == TODO; + } + + /** + * Can we have help on the keyword with type ? + * @param type the type of the keyword + * @return true if the keyword is helpable + */ + public static final boolean isHelpable(final int type) { + return type == ID + || type == COMMANDS + || type == MACROS + || type == OPERATOR + || type == FKEYWORD + || type == CKEYWORD + || type == OSKEYWORD + || type == SKEYWORD + || type == ELSEIF + || type == CONSTANTES + || type == VARIABLES + || type == FIELD; + } + + public static final boolean isSearchable(final int type) { + return type == ID + || type == COMMANDS + || type == MACROS + || type == MACROINFILE + || type == INPUTOUTPUTARGS + || type == OPERATOR + || type == FKEYWORD + || type == CKEYWORD + || type == OSKEYWORD + || type == SKEYWORD + || type == ELSEIF + || type == NUMBER + || type == CONSTANTES + || type == VARIABLES + || type == FIELD; + } + + /** + * Can we open the source file of the keyword with type ? + * @param type the type of the keyword + * @return true if the keyword is openable + */ + public static final boolean isOpenable(final int type) { + return type == MACROS || type == MACROINFILE; + } + + /** + * To know if a keyword is a part of a matching keywords + * @param type the type of the keyword + * @return true if the keyword is a part of a matching block + */ + public static final boolean isMatchable(final int type) { + return type == OPENCLOSE + || type == FKEYWORD + || type == OSKEYWORD + || type == ELSEIF; + } + + /** + * To know if a keyword is a clickable + * @param type the type of the keyword + * @return true if the keyword is clickable + */ + public static final boolean isClickable(final int type) { + return type == URL + || type == MAIL + || type == MACROS + || type == MACROINFILE; + } + + /** + * To know if a keyword is a part of a matching keywords + * @param type the type of the keyword + * @return true if the keyword is a part of a matching block + */ + public static final boolean isOpenClose(final int type) { + return type == OPENCLOSE; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabPlainView.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabPlainView.java new file mode 100755 index 000000000..fd438ed76 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabPlainView.java @@ -0,0 +1,469 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.Shape; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.awt.Toolkit; +import java.awt.Component; +import java.util.Map; + +import java.io.IOException; + +import javax.swing.text.Utilities; +import javax.swing.text.PlainView; +import javax.swing.text.Segment; +import javax.swing.text.Element; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * This important class is mainly used to render a document in using a PlainView (no line-wrapping) + * @author Calixte DENIZET + */ +public class ScilabPlainView extends PlainView { + + private static final String DESKTOPHINTS = "awt.font.desktophints"; + + private ScilabContext context; + private ScilabLexer lexer; + private ScilabDocument doc; + private Segment text = new Segment(); + private boolean isTabViewable = true; + private boolean isWhiteViewable = true; + private boolean enable = SciNotesOptions.getSciNotesDisplay().keywordsColorization; + + private int tabType; + private String tabCharacter = " "; + private int tabLength = 4; + + private int numOfColumns = 80; + private Color lineColor = new Color(220, 220, 220); + + private final Rectangle rect = new Rectangle(); + private Map desktopFontHints; + private boolean enableDesktopFontHints = true; + + private int whiteHeight; + private int whiteWidth; + + private boolean unselected = true; + + /** + * The constructor to set this view for an element with a context (containing infos + * such as colors or fonts of the keywords). + * @param elem the element to view + * @param context used to view the element + */ + ScilabPlainView(Element elem, ScilabContext context) { + super(elem); + this.context = context; + doc = (ScilabDocument) getDocument(); + if (doc.getBinary()) { + disable(); + } + doc.setView(this); + lexer = doc.createLexer(); + setTabRepresentation(ScilabView.TABVERTICAL); + } + + /** + * A tabulation can be drawn with a mark + * @param b true if viewable or not + */ + public void setTabViewable(boolean b) { + isTabViewable = b; + } + + /** + * A white can be drawn with a mark + * @param b true if viewable or not + */ + public void setWhiteViewable(boolean b) { + isWhiteViewable = b; + } + + /** + * Disable this view + */ + public void disable() { + enable = false; + } + + /** + * Enable this view + */ + public void enable() { + enable = true; + } + + /** + * Enable this view + */ + public void enable(boolean b) { + enable = b; + } + + /** + * If n > 0, then a line will be drawn to see the maximum of chars recommanded in a line + * (80 by default). + * @param n the maximum of column recommanded in this view + */ + public void setMaxColumns(int n) { + numOfColumns = n; + } + + /** + * @return the width of a white + */ + public int getWhiteWidth() { + return whiteWidth; + } + + /** + * This method can be used to draw anything you want in the editor (such as + * the line of maximum recommanded chars). + * @param g the graphics where to draw + * @param a the shape bounding the visible area + * @overload paint method in WrappedPlainView + */ + public void paint(Graphics g, Shape a) { + if (numOfColumns > 0) { + g.setColor(lineColor); + Component c = getContainer(); + g.drawLine(numOfColumns * whiteWidth, 0, numOfColumns * whiteWidth, c.getHeight()); + } + super.paint(g, a); + } + + /** + * A trick to easily determine the y-coordinate of the line n (useful in SciNotesLineNumberPanel) + * @param n the line number + * @return the y-coordinate of the line + */ + public int getLineAllocation(int n) { + rect.setLocation(0, 4); // Why 4 ?? Because it works with 4 ! + try { + return lineToRect(rect, n).y; + } catch (ArrayIndexOutOfBoundsException e) { + return 0; + } + } + + /** + * Used when the font is changed in the pane + */ + public void reinitialize() { + desktopFontHints = null; + enableDesktopFontHints = true; + } + + /** + * Very important method since we draw the text in this method !! + * @param g the graphics where to draw + * @param sx the x-coordinate where to draw + * @param sy the y-coordinate ... (guess the end pf the sentence) + * @param p0 the start of the text in the doc + * @param p1 the end of the text in the doc + * @return the x-coordinate where to draw the next piece of text + * @throws BadLocationException if p0 and p1 are bad positions in the text + */ + protected int drawUnselectedText(Graphics g, int sx, int sy, int p0, int p1) throws BadLocationException { + if (!enable) { + return super.drawUnselectedText(g, sx, sy, p0, p1); + } + + if (enableDesktopFontHints && desktopFontHints == null) { + /* This hint is used to have antialiased fonts in the view in using + the same method (differents way to antialias with LCD screen) as the desktop. */ + desktopFontHints = (Map) Toolkit.getDefaultToolkit().getDesktopProperty(DESKTOPHINTS); + calculateHeight(((Graphics2D) g).getFontRenderContext(), context.tokenFonts[0]); + enableDesktopFontHints = desktopFontHints != null; + } + + if (enableDesktopFontHints) { + ((Graphics2D) g).addRenderingHints(desktopFontHints); + } + + /* The lexer returns all tokens between the pos p0 and p1. + The value of the returned token determinates the color and the font. + The lines can be broken by the Pane so we must look at previous + and next chars to know if p0 or p1 is "inside" a token. */ + + Element elem = doc.getDefaultRootElement(); + Element line = elem.getElement(elem.getElementIndex(p0)); + + int prevTok = -1; + int tok = -1; + int mark = p0; + int start = p0; + int x = sx; + int y = sy; + boolean isBroken = false; + + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + + if (startL != start) { + //we are drawing a broken line + try { + lexer.setRange(startL, endL); + while (startL < start) { + tok = lexer.scan(); + startL = lexer.start + lexer.yychar() + lexer.yylength(); + } + isBroken = true; + } catch (IOException e) { } + } + + if (!isBroken) { + lexer.setRange(start, endL); + } + + while (start < p1 && tok != ScilabLexerConstants.EOF) { + + try { + if (!isBroken) { + tok = lexer.scan(); + } else { + isBroken = false; + } + } catch (IOException e) { } + + start = lexer.start + lexer.yychar(); + + int end = Math.min(p1, start + lexer.yylength()); + + if (end != mark) { + if (tok != prevTok) { + if (unselected) { + g.setColor(context.tokenColors[tok]); + } else { + g.setColor(Color.WHITE); + } + g.setFont(context.tokenFonts[tok]); + prevTok = tok; + } + + doc.getText(mark, end - mark, text); + + int w; + + if ((context.tokenAttrib[tok] & 1) != 0) { + w = Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, this, mark); + g.drawLine(x, y + 1, x + w, y + 1); + } + + if ((context.tokenAttrib[tok] & 2) != 0) { + w = Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, this, mark); + g.drawLine(x, y - whiteHeight, x + w, y - whiteHeight); + } + + switch (tok) { + case ScilabLexerConstants.WHITE : + case ScilabLexerConstants.WHITE_COMMENT : + case ScilabLexerConstants.WHITE_STRING : + if (isWhiteViewable) { + w = Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, this, mark); + g.drawLine(x + (w - 1) / 2, y - whiteHeight, x + (w + 1) / 2, y - whiteHeight); + } + break; + case ScilabLexerConstants.TAB : + case ScilabLexerConstants.TAB_COMMENT : + case ScilabLexerConstants.TAB_STRING : + if (isTabViewable) { + paintTab(text, x, y, g, mark); + } + break; + case ScilabLexerConstants.ERROR : + if (unselected) { + g.setColor(Color.RED); + } else { + g.setColor(Color.WHITE); + } + w = Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, this, mark); + for (int i = 0; i < w; i += 4) { + g.drawLine(x + i, y + 2, x + i + 1, y + 2); + } + for (int i = 2; i < w; i += 4) { + g.drawLine(x + i, y + 1, x + i + 1, y + 1); + } + break; + default : + break; + } + + x = Utilities.drawTabbedText(text, x, y, g, this, mark); + mark = end; + } + + start = end; + } + + return x; + } + + /** + * {@inheritDoc} + */ + protected void drawLine(int lineIndex, Graphics g, int x, int y) { + Element elem = doc.getDefaultRootElement().getElement(lineIndex); + int p0 = elem.getStartOffset(); + int p1 = elem.getEndOffset(); + ScilabEditorPane pane = (ScilabEditorPane) getContainer(); + int sel0 = pane.getSelectionStart(); + int sel1 = pane.getSelectionEnd(); + int[] selC = pane.isNearColumnSelection(p0); + + try { + if (sel0 == sel1) { + if (selC == null) { + drawUnselectedText(g, x, y, p0, p1); + return; + } + sel0 = selC[0]; + sel1 = selC[1]; + if (sel0 == sel1) { + drawUnselectedText(g, x, y, p0, p1); + return; + } + } + + if ((p0 >= sel0 && p0 <= sel1) && (p1 >= sel0 && p1 <= sel1)) { + drawSelectedText(g, x, y, p0, p1); + } else if (sel0 >= p0 && sel0 <= p1) { + if (sel1 >= p0 && sel1 <= p1) { + x = drawUnselectedText(g, x, y, p0, sel0); + x = drawSelectedText(g, x, y, sel0, sel1); + drawUnselectedText(g, x, y, sel1, p1); + } else { + x = drawUnselectedText(g, x, y, p0, sel0); + drawSelectedText(g, x, y, sel0, p1); + } + } else if (sel1 >= p0 && sel1 <= p1) { + x = drawSelectedText(g, x, y, p0, sel1); + drawUnselectedText(g, x, y, sel1, p1); + } else { + drawUnselectedText(g, x, y, p0, p1); + } + } catch (BadLocationException e) { } + } + + /** + * Draw the selected text. + * @param g the graphics where to draw + * @param sx the x-coordinate where to draw + * @param sy the y-coordinate ... (guess the end pf the sentence) + * @param p0 the start of the text in the doc + * @param p1 the end of the text in the doc + * @return the x-coordinate where to draw the next piece of text + * @throws BadLocationException if p0 and p1 are bad positions in the text + */ + protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1) throws BadLocationException { + unselected = false; + int z = drawUnselectedText(g, x, y, p0, p1); + unselected = true; + return z; + } + + /** + * Used to give the way to represent a tabulation. By default TABVERTICAL is used. + * @param type must be TABVERTICAL or TABDOUBLECHEVRONS or TABHORIZONTAL + * If a bad value is given, then nothing will be drawn + */ + public void setTabRepresentation(int type) { + this.tabType = type; + } + + /** + * Used to represent a tabulation with the given character ('|' or '#' or...) + * @param rep the char representing a tab + */ + public void setTabRepresentation(char rep) { + setTabRepresentation(ScilabView.TABCHARACTER); + this.tabCharacter = Character.toString(rep); + } + + /** + * Used to represent a tabulation + * @param tabulation a Tabulation + */ + public void setTabRepresentation(TabManager.Tabulation tabulation) { + if (tabulation.type == ScilabView.TABCHARACTER) { + setTabRepresentation(tabulation.rep); + } else { + setTabRepresentation(tabulation.type); + } + tabLength = tabulation.number; + } + + /** + * Used to represent the default tabulation got with ConfigSciNotesManager + */ + public void setDefaultTabRepresentation() { + setTabRepresentation(new TabManager.Tabulation()); + } + + /** + * Method to paint a tabulation according to the setTabRepresentation. + * @param text the segment of text representing a tabulation + * @param x the x-coordinate where to draw + * @param y the y-coordinate where to draw + * @param g the graphics ... (yeah ! once again) + * @param start the position in the document + */ + protected void paintTab(Segment text, int x, int y, Graphics g, int start) { + FontMetrics fm = g.getFontMetrics(); + int w = Utilities.getTabbedTextWidth(text, fm, x, this, start); + switch (tabType) { + case ScilabView.TABVERTICAL : + g.drawLine(x, y + 4, x, y + 4 - fm.getHeight()); + break; + case ScilabView.TABDOUBLECHEVRONS : + g.drawString("\u00BB", x, y); + break; + case ScilabView.TABHORIZONTAL : + g.drawLine(x, y - whiteHeight, x + w - 1, y - whiteHeight); + break; + case ScilabView.TABCHARACTER : + g.drawString(tabCharacter, x, y); + break; + default : + } + } + + /** + * Determinates the height of a '+' to have the vertical shift + * to draw a line which strokes the text or to draw the mark + * let by a white. + * @param frc a font context + * @param f the font where to take the '+' + */ + private void calculateHeight(FontRenderContext frc, Font f) { + TextLayout layout = new TextLayout("+", f, frc); + Rectangle2D rectangle = layout.getBounds(); + whiteHeight = (int) Math.round(-rectangle.getY() / 2); + layout = new TextLayout("w", f, frc); + rectangle = layout.getBounds(); + whiteWidth = (int) Math.round(rectangle.getWidth()); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabView.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabView.java new file mode 100755 index 000000000..04172b9f3 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/ScilabView.java @@ -0,0 +1,500 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; +import java.awt.Shape; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; +import java.awt.Toolkit; +import java.util.Map; + +import java.io.IOException; + +import javax.swing.text.Utilities; +import javax.swing.text.WrappedPlainView; +import javax.swing.text.Position; +import javax.swing.text.Segment; +import javax.swing.text.Element; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * This important class is mainly used to render a document + * @author Calixte DENIZET + */ +public class ScilabView extends WrappedPlainView { + + /** + * A tabulation can be rendered with a vertical line. + */ + public static final int TABVERTICAL = 0; + + /** + * A tabulation can be rendered with a double-chevrons. + */ + public static final int TABDOUBLECHEVRONS = 1; + + /** + * A tabulation can be rendered with an horizontal line. + */ + public static final int TABHORIZONTAL = 2; + + /** + * A tabulation can be rendered with a character. + */ + public static final int TABCHARACTER = 3; + + /** + * A tabulation can be rendered with nothing. + */ + public static final int TABNOTHING = 4; + + private static final String DESKTOPHINTS = "awt.font.desktophints"; + + private ScilabContext context; + private ScilabLexer lexer; + private ScilabDocument doc; + private Segment text = new Segment(); + private boolean isTabViewable = true; + private boolean isWhiteViewable = true; + private boolean enable = SciNotesOptions.getSciNotesDisplay().keywordsColorization; + + private int tabType; + private String tabCharacter = " "; + private int tabLength = 4; + + private int numOfColumns = 80; + private Color lineColor = new Color(220, 220, 220); + + private final Rectangle rect = new Rectangle(); + private Map desktopFontHints; + private boolean enableDesktopFontHints = true; + + private int whiteHeight; + private int whiteWidth; + + private boolean unselected = true; + + /** + * The constructor to set this view for an element with a context (containing infos + * such as colors or fonts of the keywords). + * @param elem the element to view + * @param context used to view the element + */ + ScilabView(Element elem, ScilabContext context) { + super(elem); + this.context = context; + doc = (ScilabDocument) getDocument(); + if (doc.getBinary()) { + disable(); + } + doc.setView(this); + lexer = doc.createLexer(); + setTabRepresentation(TABVERTICAL); + } + + /** + * A tabulation can be drawn with a mark + * @param b true if viewable or not + */ + public void setTabViewable(boolean b) { + isTabViewable = b; + } + + /** + * A white can be drawn with a mark + * @param b true if viewable or not + */ + public void setWhiteViewable(boolean b) { + isWhiteViewable = b; + } + + /** + * Disable this view + */ + public void disable() { + enable = false; + } + + /** + * Enable this view + */ + public void enable() { + enable = true; + } + + /** + * Enable this view + */ + public void enable(boolean b) { + enable = b; + } + + /** + * If n > 0, then a line will be drawn to see the maximum of chars recommanded in a line + * (80 by default). + * @param n the maximum of column recommanded in this view + */ + public void setMaxColumns(int n) { + numOfColumns = n; + } + + /** + * @return the width of a white + */ + public int getWhiteWidth() { + return whiteWidth; + } + + /** + * This method can be used to draw anything you want in the editor (such as + * the line of maximum recommanded chars). + * @param g the graphics where to draw + * @param a the shape bounding the visible area + * @overload paint method in WrappedPlainView + */ + public void paint(Graphics g, Shape a) { + if (numOfColumns > 0) { + g.setColor(lineColor); + g.drawLine(numOfColumns * whiteWidth, 0, numOfColumns * whiteWidth, getHeight()); + } + super.paint(g, a); + } + + /** + * A trick to be sure that all the line is covered by an highlight + * {@inheritDoc} + */ + public Shape modelToView(int p0, Position.Bias b0, int p1, Position.Bias b1, Shape a) throws BadLocationException { + Rectangle r = (Rectangle) super.modelToView(p0, b0, p1, b1, a); + r.width = ((Rectangle) a).width; + return r; + } + + /** + * A trick to easily determine the y-coordinate of the line n (useful in SciNotesLineNumberPanel) + * @param n the line number + * @return the y-coordinate of the line + */ + public int getLineAllocation(int n) { + rect.setLocation(0, 4); // Why 4 ?? Because it works with 4 ! + try { + childAllocation(n, rect); + } catch (ArrayIndexOutOfBoundsException e) { } + return rect.y; + } + + /** + * Used when the font is changed in the pane + */ + public void reinitialize() { + desktopFontHints = null; + enableDesktopFontHints = true; + } + + /** + * Very important method since we draw the text in this method !! + * @param g the graphics where to draw + * @param sx the x-coordinate where to draw + * @param sy the y-coordinate ... (guess the end of the sentence) + * @param p0 the start of the text in the doc + * @param p1 the end of the text in the doc + * @return the x-coordinate where to draw the next piece of text + * @throws BadLocationException if p0 and p1 are bad positions in the text + */ + protected int drawUnselectedText(Graphics g, int sx, int sy, int p0, int p1) throws BadLocationException { + if (!enable) { + return super.drawUnselectedText(g, sx, sy, p0, p1); + } + + if (enableDesktopFontHints && desktopFontHints == null) { + /* This hint is used to have antialiased fonts in the view in using + the same method (differents way to antialias with LCD screen) as the desktop. */ + desktopFontHints = (Map) Toolkit.getDefaultToolkit().getDesktopProperty(DESKTOPHINTS); + calculateHeight(((Graphics2D) g).getFontRenderContext(), context.tokenFonts[0]); + enableDesktopFontHints = desktopFontHints != null; + } + + if (enableDesktopFontHints) { + ((Graphics2D) g).addRenderingHints(desktopFontHints); + } + + /* The lexer returns all tokens between the pos p0 and p1. + The value of the returned token determinates the color and the font. + The lines can be broken by the Pane so we must look at previous + and next chars to know if p0 or p1 is "inside" a token. */ + + Element elem = doc.getDefaultRootElement(); + Element line = elem.getElement(elem.getElementIndex(p0)); + + FontMetrics metrics = g.getFontMetrics(); + + int prevTok = -1; + int tok = -1; + int mark = p0; + int start = p0; + int x = sx; + int y = sy; + boolean isBroken = false; + + int startL = line.getStartOffset(); + int endL = line.getEndOffset(); + + if (startL != start) { + //we are drawing a broken line + try { + lexer.setRange(startL, endL); + while (startL < start) { + tok = lexer.scan(); + startL = lexer.start + lexer.yychar() + lexer.yylength(); + } + isBroken = true; + } catch (IOException e) { } + } + + if (!isBroken) { + lexer.setRange(start, endL); + } + + while (start < p1 && tok != ScilabLexerConstants.EOF) { + try { + if (!isBroken) { + tok = lexer.scan(); + } else { + isBroken = false; + } + } catch (IOException e) { } + + start = lexer.start + lexer.yychar(); + int end = Math.min(p1, start + lexer.yylength()); + + if (end != mark) { + if (tok != prevTok) { + if (unselected) { + g.setColor(context.tokenColors[tok]); + } else { + g.setColor(Color.WHITE); + } + g.setFont(context.tokenFonts[tok]); + prevTok = tok; + } + + doc.getText(mark, end - mark, text); + + int w; + + if ((context.tokenAttrib[tok] & 1) != 0) { + w = Utilities.getTabbedTextWidth(text, metrics, x, this, mark); + g.drawLine(x, y + 1, x + w, y + 1); + } + + if ((context.tokenAttrib[tok] & 2) != 0) { + w = Utilities.getTabbedTextWidth(text, metrics, x, this, mark); + g.drawLine(x, y - whiteHeight, x + w, y - whiteHeight); + } + + switch (tok) { + case ScilabLexerConstants.WHITE : + case ScilabLexerConstants.WHITE_COMMENT : + case ScilabLexerConstants.WHITE_STRING : + if (isWhiteViewable) { + w = Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, this, mark); + g.drawLine(x + (w - 1) / 2, y - whiteHeight, x + (w + 1) / 2, y - whiteHeight); + } + break; + case ScilabLexerConstants.TAB : + case ScilabLexerConstants.TAB_COMMENT : + case ScilabLexerConstants.TAB_STRING : + if (isTabViewable) { + paintTab(text, x, y, g, mark); + } + break; + case ScilabLexerConstants.ERROR : + if (unselected) { + g.setColor(Color.RED); + } else { + g.setColor(Color.WHITE); + } + w = Utilities.getTabbedTextWidth(text, g.getFontMetrics(), x, this, mark); + for (int i = 0; i < w; i += 4) { + g.drawLine(x + i, y + 2, x + i + 1, y + 2); + } + for (int i = 2; i < w; i += 4) { + g.drawLine(x + i, y + 1, x + i + 1, y + 1); + } + break; + default : + break; + } + + x = Utilities.drawTabbedText(text, x, y, g, this, mark); + mark = end; + } + + start = end; + } + + return x; + } + + /** + * {@inheritDoc} + */ + protected void drawLine(int p0, int p1, Graphics g, int x, int y) { + ScilabEditorPane pane = (ScilabEditorPane) getContainer(); + int sel0 = pane.getSelectionStart(); + int sel1 = pane.getSelectionEnd(); + int[] selC = pane.isNearColumnSelection(p0); + p1 = Math.min(doc.getLength(), p1); + + try { + if (sel0 == sel1) { + if (selC == null) { + drawUnselectedText(g, x, y, p0, p1); + return; + } + sel0 = selC[0]; + sel1 = selC[1]; + if (sel0 == sel1) { + drawUnselectedText(g, x, y, p0, p1); + return; + } + } + + if ((p0 >= sel0 && p0 <= sel1) && (p1 >= sel0 && p1 <= sel1)) { + drawSelectedText(g, x, y, p0, p1); + } else if (sel0 >= p0 && sel0 <= p1) { + if (sel1 >= p0 && sel1 <= p1) { + x = drawUnselectedText(g, x, y, p0, sel0); + x = drawSelectedText(g, x, y, sel0, sel1); + drawUnselectedText(g, x, y, sel1, p1); + } else { + x = drawUnselectedText(g, x, y, p0, sel0); + drawSelectedText(g, x, y, sel0, p1); + } + } else if (sel1 >= p0 && sel1 <= p1) { + x = drawSelectedText(g, x, y, p0, sel1); + drawUnselectedText(g, x, y, sel1, p1); + } else { + drawUnselectedText(g, x, y, p0, p1); + } + } catch (BadLocationException e) { } + } + + /** + * Draw the selected text. + * @param g the graphics where to draw + * @param sx the x-coordinate where to draw + * @param sy the y-coordinate ... (guess the end pf the sentence) + * @param p0 the start of the text in the doc + * @param p1 the end of the text in the doc + * @return the x-coordinate where to draw the next piece of text + * @throws BadLocationException if p0 and p1 are bad positions in the text + */ + protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1) throws BadLocationException { + unselected = false; + int z = drawUnselectedText(g, x, y, p0, p1); + unselected = true; + return z; + } + + /** + * Used to give the way to represent a tabulation. By default TABVERTICAL is used. + * @param type must be TABVERTICAL or TABDOUBLECHEVRONS or TABHORIZONTAL + * If a bad value is given, then nothing will be drawn + */ + public void setTabRepresentation(int type) { + this.tabType = type; + } + + /** + * Used to represent a tabulation with the given character ('|' or '#' or...) + * @param rep the char representing a tab + */ + public void setTabRepresentation(char rep) { + setTabRepresentation(TABCHARACTER); + this.tabCharacter = Character.toString(rep); + } + + /** + * Used to represent a tabulation + * @param tabulation a Tabulation + */ + public void setTabRepresentation(TabManager.Tabulation tabulation) { + if (tabulation.type == TABCHARACTER) { + setTabRepresentation(tabulation.rep); + } else { + setTabRepresentation(tabulation.type); + } + tabLength = tabulation.number; + } + + /** + * Used to represent the default tabulation got with ConfigSciNotesManager + */ + public void setDefaultTabRepresentation() { + setTabRepresentation(new TabManager.Tabulation()); + } + + /** + * Method to paint a tabulation according to the setTabRepresentation. + * @param text the segment of text representing a tabulation + * @param x the x-coordinate where to draw + * @param y the y-coordinate where to draw + * @param g the graphics ... (yeah ! once again) + * @param start the position in the document + */ + protected void paintTab(Segment text, int x, int y, Graphics g, int start) { + FontMetrics fm = g.getFontMetrics(); + int w = Utilities.getTabbedTextWidth(text, fm, x, this, start); + switch (tabType) { + case TABVERTICAL : + g.drawLine(x, y + 4, x, y + 4 - fm.getHeight()); + break; + case TABDOUBLECHEVRONS : + g.drawString("\u00BB", x, y); + break; + case TABHORIZONTAL : + g.drawLine(x, y - whiteHeight, x + w - 1, y - whiteHeight); + break; + case TABCHARACTER : + g.drawString(tabCharacter, x, y); + break; + default : + } + } + + /** + * Determinates the height of a '+' to have the vertical shift + * to draw a line which strokes the text or to draw the mark + * let by a white. + * @param frc a font context + * @param f the font where to take the '+' + */ + private void calculateHeight(FontRenderContext frc, Font f) { + TextLayout layout = new TextLayout("+", f, frc); + Rectangle2D rectangle = layout.getBounds(); + whiteHeight = (int) Math.round(-rectangle.getY() / 2); + layout = new TextLayout("w", f, frc); + rectangle = layout.getBounds(); + whiteWidth = (int) Math.round(rectangle.getWidth()); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/SearchManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/SearchManager.java new file mode 100755 index 000000000..27df6783e --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/SearchManager.java @@ -0,0 +1,825 @@ +/* Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bernard HUGUENEY + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FilenameFilter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.SwingWorker; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.tree.DefaultMutableTreeNode; + +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.commons.xml.ScilabXMLUtilities; +import org.scilab.modules.scinotes.utils.SciNotesMessages; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * Class SearchManager + * @author Sylvestre Koumar + * @author Calixte DENIZET + */ +public class SearchManager { + + private static final ImageIcon FILEIMAGE = new ImageIcon(FindIconHelper.findIcon("stock_search")); + private static final ImageIcon SCILABFILEIMAGE = new ImageIcon(FindIconHelper.findIcon("scilab_search")); + private static final ImageIcon FOLDERIMAGE = new ImageIcon(FindIconHelper.findIcon("folder-saved-search")); + private static final ImageIcon LINEICON = new ImageIcon(FindIconHelper.findIcon("line-found")); + + /** + * FIND AND REPLACE START + * @param scilabDocument document + * @param word string + * @param start int + * @param end int + * @param caseSensitive boolean + * @param wholeWord boolean + * @param useRegexp boolean + * @return List + */ + public static List<Integer[]> findWord(Document scilabDocument, String word, + int start, int end, + boolean caseSensitive, boolean wholeWord, boolean useRegexp) { + String fullText = ""; + try { + fullText = scilabDocument.getText(start, end - start + 1); + } catch (BadLocationException ex) { + ex.printStackTrace(); + } + + if (fullText.length() == 0) { + return null; + } + + List<Integer[]> offsetList = new ArrayList<Integer[]>(); + + //If we don't give any word to find + if (word != null && !word.equals("")) { + Pattern pattern = generatePattern(word, caseSensitive, wholeWord, useRegexp); + Matcher matcher = pattern.matcher(fullText); + + while (matcher.find()) { + if (matcher.start() != matcher.end()) { + offsetList.add(new Integer[] {matcher.start() + start, matcher.end() + start}); + } + } + } + + return offsetList; + } + + /** + * FIND AND REPLACE START + * @param scilabDocument document + * @param word string + * @param start int + * @param end int + * @param caseSensitive boolean + * @param wholeWord boolean + * @param useRegexp boolean + * @return List + */ + public static List<Integer[]> findToken(ScilabDocument scilabDocument, int token, ScilabLexer lexer, Pattern pat) { + String fullText = scilabDocument.getText(); + + if (fullText.length() == 0) { + return null; + } + + List<Integer[]> offsetList = new ArrayList<Integer[]>(); + + //If we don't give any word to find + Matcher matcher = pat.matcher(fullText); + + while (matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + if (token == -1 || token == lexer.getKeyword(start, false)) { + offsetList.add(new Integer[] {start, end}); + } + } + + return offsetList; + } + + /** + * Generate the good pattern according to the differents boolean + * @param exp the searched expression + * @param caseSensitive boolean + * @param wholeWord boolean + * @param useRegexp boolean + * @return the pattern + */ + public static Pattern generatePattern(String exp, boolean caseSensitive, boolean wholeWord, boolean useRegexp) { + String word = exp; + if (word != null && !word.equals("")) { + if (!useRegexp) { + word = word.replace("\\E", "\\E\\\\E\\Q"); + word = "\\Q" + word + "\\E"; + if (wholeWord && exp.matches("\\b.*\\b")) { + word = "\\b" + word + "\\b"; + } + } + + if (!caseSensitive) { + word = "(?i)" + word; + } + + if (useRegexp) { + word = "(?m)" + word; + } + + return Pattern.compile(word); + } else { + return Pattern.compile(""); + } + } + + /** + * Search a word (with a pattern) in files selected according to their name. + * @param base the base directory + * @param recursive, if true then a recursive search is made + * @param ignoreCR, if true then the read file is considered as one line and regex pattern can include \n + * @param filePattern the pattern to use to select the files. * is equivalent to .* and ? to .? + * @param fileCaseSensitive, if true then the file pattern is case sensitive + * @param wordPattern the pattern of the word to search + * @param wordCaseSensitive, if true then the word pattern is case sensitive + * @param wholeWord, if true only whole word will be matched, e.g. in "foobar foo bar", if the pattern is "foo", then only the second "foo" will be matched + * @param regexp, if true the word pattern is considered as a regex + * @return infos with the matching positions + */ + public static MatchingPositions searchInFiles(final BackgroundSearch bgs, String base, final boolean recursive, final boolean ignoreCR, + String filePattern, boolean fileCaseSensitive, + String wordPattern, boolean wordCaseSensitive, boolean wholeWord, boolean regexp) { + final File dir = new File(base); + Pattern word = null; + if (wordPattern != null && wordPattern.length() != 0) { + word = generatePattern(wordPattern, wordCaseSensitive, wholeWord, regexp); + } + filePattern = filePattern.replace(".", "\\.").replace("*", ".*").replace("?", ".?"); + final Pattern file = generatePattern(filePattern, fileCaseSensitive, false, true); + + final boolean[] killed = new boolean[] {false}; + if (bgs == null) { + return searchInFiles(killed, dir, recursive, ignoreCR, file, word); + } else { + final Pattern fword = word; + SwingWorker worker = new SwingWorker<Object, Object>() { + @Override + public Object doInBackground() { + long begin = System.currentTimeMillis(); + bgs.setResults(searchInFiles(killed, dir, recursive, ignoreCR, file, fword)); + long end = System.currentTimeMillis(); + bgs.setElapsedTime(end - begin); + return null; + } + + @Override + public void done() { + bgs.done(); + } + }; + bgs.setKilled(killed); + bgs.setSwingWorker(worker); + worker.execute(); + return null; + } + } + + /** + * Search a word (with a pattern) in files selected according to their name. + * @param base the base directory + * @param recursive, if true then a recursive search is made + * @param ignoreCR, if true then the read file is considered as one line and regex pattern can include \n + * @param filePattern the pattern to use to select the files. * is equivalent to .* and ? to .? + * @param word the pattern of the word to search + * @param killed a boolean array with more than one element. It is used as a reference on a boolean set to true if the process is killed. + * @return infos with the matching positions + */ + public static MatchingPositions searchInFiles(boolean[] killed, File base, boolean recursive, boolean ignoreCR, final Pattern file, final Pattern word) { + MatchingPositions pos = null; + if (base.exists() && base.isDirectory() && base.canRead() && !killed[0]) { + List<MatchingPositions> list = new ArrayList<MatchingPositions>(); + pos = new MatchingPositions(base.getAbsolutePath(), list); + int occurences = 0; + File[] files = base.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + File f = new File(dir, name); + return f.isFile() && f.canRead() && file.matcher(name).matches(); + } + }); + Arrays.sort(files); + + if (word != null) { + for (int i = 0; i < files.length && !killed[0]; i++) { + MatchingPositions wpos; + if (!ignoreCR) { + wpos = searchWordInFile(files[i], word); + } else { + wpos = searchWordInFileIgnoringCR(files[i], word); + } + if (wpos != null && wpos.getOccurences() != 0) { + list.add(wpos); + occurences += wpos.getOccurences(); + } + } + } else { + for (int i = 0; i < files.length && !killed[0]; i++) { + list.add(new MatchingPositions(files[i].getAbsolutePath())); + } + occurences += files.length; + } + + if (recursive) { + files = base.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + File d = new File(dir, name); + return d.isDirectory() && d.canRead(); + } + }); + Arrays.sort(files); + + for (int i = 0; i < files.length && !killed[0]; i++) { + MatchingPositions rpos = searchInFiles(killed, files[i], true, ignoreCR, file, word); + if (rpos != null) { + list.add(rpos); + occurences += rpos.getOccurences(); + } + } + } + + pos.setOccurences(occurences); + + if (list.isEmpty()) { + return null; + } + } + + return pos; + } + + /** + * Search a word (with a pattern) in a file. The search is made line by line. + * @param file the file where to search + * @param pat the pattern of the word to search + * @return infos with the matching positions + */ + public static MatchingPositions searchWordInFile(File f, Pattern pat) { + if (f.exists() && f.canRead()) { + MatchingPositions pos = new MatchingPositions(f.getAbsolutePath()); + String charset; + try { + charset = ScilabEditorKit.tryToGuessEncoding(f).name(); + } catch (Exception e) { + charset = Charset.defaultCharset().name(); + } + + try { + Scanner scanner = new Scanner(f, charset); + int occ = 0; + int line = 0; + while (scanner.hasNextLine()) { + line++; + String str = scanner.nextLine(); + Matcher matcher = pat.matcher(str); + int socc = occ; + while (matcher.find()) { + occ++; + } + if (occ != socc) { + pos.addLine(line, str, pat); + } + } + scanner.close(); + + pos.setOccurences(occ); + return pos; + } catch (Exception e) { } + } + + return null; + } + + /** + * Search a word (with a pattern) in a file. The file content is considered as one line (useful to search "...\n...") + * @param file the file where to search + * @param pat the pattern of the word to search + * @return infos with the matching positions + */ + public static MatchingPositions searchWordInFileIgnoringCR(File f, Pattern pat) { + if (f.exists() && f.canRead()) { + MatchingPositions pos = new MatchingPositions(f.getAbsolutePath()); + String charset; + try { + charset = ScilabEditorKit.tryToGuessEncoding(f).name(); + } catch (Exception e) { + charset = Charset.defaultCharset().name(); + } + + try { + Scanner scanner = new Scanner(f, charset); + int occ = 0; + while (scanner.findWithinHorizon(pat, 0) != null) { + occ++; + } + pos.setOccurences(occ); + scanner.close(); + + return pos; + } catch (Exception e) { } + } + + return null; + } + + /** + * Count the file having a name corresponding to a pattern + * @param base the base directory + * @param pat the file name pattern + * @return the number of files + */ + public static int countFiles(File base, Pattern pat) { + if (!base.isDirectory() || !base.canRead()) { + return -1; + } + + int[] count = new int[] {0}; + countFiles(base, pat, count); + + return count[0]; + } + + /** + * Count files in a recursive way + */ + private static void countFiles(File base, final Pattern pat, final int[] count) { + File[] files = base.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + File f = new File(dir, name); + if (f.isFile() && f.canRead() && pat.matcher(name).matches()) { + count[0]++; + } else if (f.isDirectory() && f.canRead()) { + countFiles(f, pat, count); + } + return false; + } + }); + } + + /** + * @param file the file to test + * @return true if it is a binary file + */ + public static boolean isBinaryFile(File f) { + try { + BufferedReader reader = new BufferedReader(new FileReader(f)); + char[] buffer = new char[8192]; + int len = reader.read(buffer, 0, 8192); + reader.close(); + int i = 0; + if (len != -1) { + for (; i < len && buffer[i] != '\0'; i++) { + ; + } + } + + return len != -1 && i != len; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + private static void indent(BufferedWriter buffer, int level) throws IOException { + for (int i = 0; i < level; i++) { + buffer.append(" "); + } + } + + /** + * MatchingPositions: inner class to store the results of a search in a file or in a directory + */ + public static class MatchingPositions implements Iconable { + + private final String file; + private boolean isRoot; + private Icon icon; + private int occurences; + private List<MatchingPositions> children; + private final List<Line> lines = new ArrayList<Line>(); + + /** + * Constructor + * @param file the file where to search is made + * @param children the list of the file in the directory + */ + public MatchingPositions(String file, List<MatchingPositions> children) { + this.file = file; + this.children = children; + setIcon(); + } + + /** + * Constructor + * @param file the file where to search is made + */ + public MatchingPositions(String file) { + this(file, null); + } + + /** + * @param root the xml Element representing a MatchingPositions + */ + public MatchingPositions(Element root) { + this.file = root.getAttribute("file"); + this.isRoot = Boolean.parseBoolean(root.getAttribute("isRoot")); + this.occurences = Integer.parseInt(root.getAttribute("occurences")); + if (root.hasChildNodes()) { + NodeList nodeList = root.getChildNodes(); + Element e = (Element) nodeList.item(1); + if (e.getTagName().equals("Position")) { + this.children = new ArrayList<MatchingPositions>(); + for (int i = 0; i < nodeList.getLength(); i++) { + if (nodeList.item(i) instanceof Element) { + e = (Element) nodeList.item(i); + this.children.add(new MatchingPositions(e)); + } + } + } else { + for (int i = 0; i < nodeList.getLength(); i++) { + if (nodeList.item(i) instanceof Element) { + e = (Element) nodeList.item(i); + this.lines.add(new Line(e)); + } + } + } + } + setIcon(); + } + + private void setIcon() { + if (children != null) { + this.icon = FOLDERIMAGE; + } else if (file.endsWith(".sce") || file.endsWith(".sci")) { + this.icon = SCILABFILEIMAGE; + } else { + this.icon = FILEIMAGE; + } + } + + /** + * Set this as the root directory + */ + public void setRoot() { + isRoot = true; + } + + /** + * Set the number of matches in the file or in the directory + * @param occ the number of matches + */ + public void setOccurences(int occ) { + occurences = occ; + } + + /** + * @return the number of matches + */ + public int getOccurences() { + return occurences; + } + + /** + * Add a line where the searched word has been found + * @param number the line number + * @param line the line content + * @param pat the pattern used + */ + public void addLine(int number, String line, Pattern pat) { + this.lines.add(new Line(number, line, pat)); + } + + /** + * @return the file name + */ + public String getFileName() { + return file; + } + + /** + * @return true if we are in a directory + */ + public boolean isDirectory() { + return children != null; + } + + /** + * {@inheritDoc} + */ + @Override + public Icon getIcon() { + return icon; + } + + /** + * @return true if the file have matching lines + */ + public boolean hasLines() { + return !lines.isEmpty(); + } + + /** + * @return the file present in this directory + */ + public List<MatchingPositions> getChildren() { + return children; + } + + /** + * Convert this MatchingPositions and its children (if they are) in a DefaultMutableTreeNode + * @return the coirresponding DefaultMutableTreeNode + */ + public DefaultMutableTreeNode toDefaultMutableTreeNode() { + DefaultMutableTreeNode root = new DefaultMutableTreeNode(this); + if (children != null && !children.isEmpty()) { + for (int i = 0; i < children.size(); i++) { + root.add(children.get(i).toDefaultMutableTreeNode()); + } + } else if (!lines.isEmpty()) { + for (Line l : lines) { + root.add(new DefaultMutableTreeNode(l)); + } + } + + return root; + } + + /** + * @param buffer the buffer where to write the XML + * @param level the indentation level + */ + public void toXML(BufferedWriter buffer, int level) throws IOException { + indent(buffer, level); + buffer.append("<Position file=\"" + ScilabXMLUtilities.getXMLString(file) + "\" isRoot=\"" + isRoot + "\" occurences=\"" + occurences + "\""); + if (children != null && !children.isEmpty()) { + buffer.append(">\n"); + for (int i = 0; i < children.size(); i++) { + children.get(i).toXML(buffer, level + 1); + } + indent(buffer, level); + buffer.append("</Position>\n"); + } else if (!lines.isEmpty()) { + buffer.append(">\n"); + for (Line l : lines) { + l.toXML(buffer, level + 1); + } + indent(buffer, level); + buffer.append("</Position>\n"); + } else { + buffer.append("/>\n"); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + String occ = SciNotesMessages.MATCHES; + if (occurences <= 1) { + occ = SciNotesMessages.MATCH; + } + + String filename; + if ((!isDirectory() && occurences != 0)) { + filename = new File(getFileName()).getName(); + } else if (isRoot) { + filename = getFileName(); + } else { + filename = new File(getFileName()).getName(); + } + + if (occurences == 0 && !isRoot) { + return filename; + } + + filename = filename.replace("&", "&").replace("/", "/").replace("\\", "\").replace("<", "<").replace(">", ">"); + return String.format(occ, filename, occurences); + } + } + + /** + * Line: inner class to store a line number and line content + */ + public static class Line implements Iconable { + + private final int number; + private String content; + + /** + * Constructor + * @param number the line number + * @param content the line content + * @param pattern the used pattern + */ + public Line(int number, String content, Pattern pattern) { + this.number = number; + Matcher matcher = pattern.matcher(content); + if (content.length() > 128) { + content = content.substring(0, 128) + "..."; + } + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + /* + TODO: Find a better way to handle <b> and </b> around the pattern. + If HTML entities are put before the loop the pattern should be updated (not a funky task...). + Actually, it could have a bad rendering on binary files (which probably contains \0...) + */ + matcher.appendReplacement(sb, "\0"); + sb.append(matcher.group()); + sb.append("\0\0"); + } + matcher.appendTail(sb); + this.content = sb.toString(); + this.content = this.content.replace("&", "&").replace("/", "/").replace("\\", "\").replace("<", "<").replace(">", ">").replace("\0\0", "</b>").replace("\0", "<b>"); + } + + /** + * @param root the xml Element representing a Line + */ + public Line(Element root) { + this.number = Integer.parseInt(root.getAttribute("number")); + this.content = root.getAttribute("content"); + } + + /** + * @return the line number + */ + public int getNumber() { + return number; + } + + /** + * @return the line content as HTML + */ + public String getContent() { + return content; + } + + /** + * {@inheritDoc} + */ + @Override + public Icon getIcon() { + return LINEICON; + } + + /** + * @param buffer the buffer where to write the XML + * @param level the indentation level + */ + public void toXML(BufferedWriter buffer, int level) throws IOException { + indent(buffer, level); + buffer.append("<Line content=\"" + ScilabXMLUtilities.getXMLString(content) + "\" number=\"" + number + "\"/>\n"); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return "<html><u>line " + number + "</u> : " + content + "</html>"; + } + } + + /** + * Inner interface for the JTree representation + */ + public static interface Iconable { + + /** + * @return the icon used in the JTree representation + */ + public Icon getIcon(); + } + + /** + * Inner class to allow a background search + */ + public static abstract class BackgroundSearch { + + private MatchingPositions pos; + private SwingWorker worker; + private long time; + private boolean[] killed; + + /** + * Default Constructor + */ + public BackgroundSearch() { } + + /** + * Stop this search + */ + public void stop() { + if (worker != null && !isDone()) { + worker.cancel(true); + worker = null; + if (killed != null && killed.length >= 1) { + killed[0] = true; + } + } + } + + /** + * Called when the work is done + */ + public abstract void done(); + + /** + * @return true if the search is finished + */ + public boolean isDone() { + if (worker != null) { + return worker.isDone(); + } + return true; + } + + /** + * Get the results + * @return the results + */ + public MatchingPositions getResults() { + if (isDone()) { + worker = null; + return pos; + } + return null; + } + + /** + * Set the elapsed time for this search + */ + public void setElapsedTime(long t) { + this.time = t; + } + + /** + * @return the elapsed time of this search + */ + public long getElapsedTime() { + return time; + } + + /** + * Set the SwingWorker we work with + * @param worker the SwingWorker + */ + private void setSwingWorker(SwingWorker worker) { + this.worker = worker; + } + + /** + * @param killed a reference on a boolean to inform the main loop that the process has been killed + */ + private void setKilled(boolean[] killed) { + this.killed = killed; + } + + /** + * @param pos the results to set + */ + private void setResults(MatchingPositions pos) { + this.pos = pos; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/TabManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/TabManager.java new file mode 100755 index 000000000..b804189b6 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/TabManager.java @@ -0,0 +1,304 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +/** + * This class handles the tabulation + * @author Calixte DENIZET + */ +public class TabManager { + + private static final String EOL = "\n"; + + private String tab; + private int lengthTab; + private ScilabDocument doc; + private Element elem; + private IndentManager indent; + private boolean isTabInsertable = true; + + /** + * We can link this TabManager with an IndentManager just to say that the size of a tabulation changed + * @param doc the document + * @param indent an IndentManager + */ + public TabManager(ScilabDocument doc, IndentManager indent) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + this.indent = indent; + setTabulation(' ', 3); + } + + /** + * Set the type and the size of a tabulation + * @param tab is a char : ' ' or '\t' + * @param n is the length of a tab + */ + public void setTabulation(char tab, int n) { + if (tab == ' ') { + this.tab = " "; + lengthTab = n; + } else { + this.tab = "\t"; + lengthTab = 1; + } + doc.putProperty("tabSize", new Integer(Math.max(n, 1))); + if (indent != null) { + indent.setProperties(tab, SciNotesOptions.getSciNotesDisplay().indentSize); + } + } + + public String getTabulationString(int position) { + if (tab.equals(" ")) { + Element startL = elem.getElement(elem.getElementIndex(position)); + int sstart = position - startL.getStartOffset(); + int len = lengthTab - (sstart % lengthTab); + if (len == 0) { + len = lengthTab; + } + char[] str = new char[len]; + for (int i = 0; i < len; i++) { + str[i] = ' '; + } + + return new String(str); + } else { + return tab; + } + } + + public String getBasicTabulationString() { + if (tab.equals(" ")) { + char[] str = new char[lengthTab]; + for (int i = 0; i < lengthTab; i++) { + str[i] = ' '; + } + + return new String(str); + } else { + return tab; + } + } + + /** + * Set the type and the size of a tabulation + * @param tabulation a Tabulation + */ + public void setTabulation(Tabulation tabulation) { + setTabulation(tabulation.tab, tabulation.number); + } + + /** + * Set the type and the size of a tabulation + */ + public void setDefaultTabulation() { + setTabulation(new Tabulation()); + } + + /** + * Insert a tab inside a line (true) or tabify a line (false) + * @param b the boolean + */ + public void setTabInsertable(boolean b) { + isTabInsertable = b; + } + + /** + * @return a String which represents a tab + */ + public String getTabulation() { + return tab; + } + + /** + * Insert a tab just after the caret position (depends on setTabInsertable) + * @param position the position in the doc + * @return the length of a tab + */ + public int insertTab(int position) { + try { + if (isTabInsertable) { + String tab = getTabulationString(position); + doc.insertString(position, tab, null); + + return tab.length(); + } else { + tabifyLines(position, position - 1); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + return lengthTab; + } + + /** + * Tabify several lines. + * @param start the starting position in the doc + * @param end the ending position in the doc + * @return the new positions of the selected text + */ + public int[] tabifyLines(int start, int end) { + Element startL = elem.getElement(elem.getElementIndex(start)); + int sstart = startL.getStartOffset(); + int[] ret = new int[] {0, 0}; + int send = end; + + try { + String str = doc.getText(sstart, send - sstart + 1); + if (str.charAt(str.length() - 1) == EOL.charAt(0)) { + send--; + str = str.substring(0, str.length() - 1); + ret[1]++; + } + String tab = getTabulationString(start); + String plainTab = getTabulationString(0); + String rep = EOL + plainTab; + str = tab + str.replaceAll(EOL, rep); + ret[0] = start + tab.length(); + ret[1] += sstart + str.length(); + doc.replace(sstart, send - sstart + 1, str, null); + return ret; + } catch (BadLocationException e) { + e.printStackTrace(); + return null; + } + } + + /** + * Suppress a tabulation just before the position or untabify line (depends on setTabInsertable) + * @param position of the caret + * @return the length of a tab + */ + public int removeTab(int position) { + try { + if (isTabInsertable) { + int pos = Math.max(0, position - lengthTab); + if (tab.equals(doc.getText(pos, lengthTab))) { + doc.remove(pos, lengthTab); + } else { + return 0; + } + } else { + untabifyLine(position); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + return lengthTab; + } + + /** + * Delete a tab at the beginning of a line where the caret is if possible. + * @param position the position in the doc + */ + public void untabifyLine(int position) { + IndentScanner iscan = indent.getIndentScanner(); + int line = elem.getElementIndex(position); + int n = iscan.getTabsAtBeginning(line); + + try { + if (n >= lengthTab) { + doc.remove(elem.getElement(line).getStartOffset(), lengthTab); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Remove one tabulation step from every line starting with tabulation between start and end + * @param start the starting position in the doc + * @param end the ending position in the doc + * @return the new positions of the selected text + */ + public int[] untabifyLines(int start, int end) { + int sstart = elem.getElement(elem.getElementIndex(start)).getStartOffset(); + int[] ret = new int[2]; + ret[0] = start; + + try { + String str = doc.getText(sstart, end - sstart + 1); + String untab = EOL + getBasicTabulationString(); + str = str.replaceAll(untab, EOL); + IndentScanner iscan = indent.getIndentScanner(); + int n = iscan.getTabsAtBeginning(elem.getElementIndex(sstart)); + if (n >= lengthTab) { + str = str.substring(lengthTab); + if (start - sstart + 1 >= lengthTab) { + ret[0] = start - lengthTab; + } + } + ret[1] = sstart + str.length(); + + doc.replace(sstart, end - sstart + 1, str, null); + } catch (BadLocationException e) { + e.printStackTrace(); + return null; + } + + return ret; + } + + /** + * Inner class to represent a tabulation + */ + public static class Tabulation { + + /** + * Should be '\t' or ' ' + */ + public char tab; + + /** + * The number of whites equivalent at this tabulation + */ + public int number; + + /** + * Should be one of the constants of ScilabView + */ + public int type; + + /** + * If type is ScilabView.TABCHARACTER, then rep is the char representing a tabulation + * in the view + */ + public char rep; + + /** + * Constructor + * @param tab '\t' or ' ' + * @param number the number of whites + * @param type see the constants in ScilabView + * @param rep the char to represent a tabulation in a view + */ + public Tabulation(char tab, int number, int type, char rep) { + this.tab = tab; + this.number = number; + this.type = type; + this.rep = rep; + } + + public Tabulation() { + this.tab = SciNotesOptions.getSciNotesDisplay().useSpaces ? ' ' : '\t'; + this.number = SciNotesOptions.getSciNotesDisplay().tabSize; + this.type = SciNotesOptions.getSciNotesDisplay().tabRepresentation; + this.rep = ' '; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/TrailingWhiteManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/TrailingWhiteManager.java new file mode 100755 index 000000000..2bda42b99 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/TrailingWhiteManager.java @@ -0,0 +1,91 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +/** + * This class handles the tabulation + * @author Calixte DENIZET + */ +public class TrailingWhiteManager { + + private static final String REGEXP_WHITES_AT_END = "[ \t]+$"; + private static final String REGEXP_WHITES_AT_EOL = "[ \t]+\n"; + + private ScilabDocument doc; + private Element elem; + + /** + * The constructor + * @param doc the document + */ + public TrailingWhiteManager(ScilabDocument doc) { + this.doc = doc; + this.elem = doc.getDefaultRootElement(); + } + + /** + * Remove the trailing blanks at the end of the line containing position + * @param position the position in the doc + */ + public int removeTrailingWhite(int position) { + int nline = elem.getElementIndex(position); + Element line = elem.getElement(nline); + int start = line.getStartOffset(); + int end = line.getEndOffset() - 1; + + try { + String str = doc.getText(start, end - start); + str = str.replaceFirst(REGEXP_WHITES_AT_END, ""); + doc.replace(start, end - start, str, null); + return Math.min(position, start + str.length()); + } catch (BadLocationException e) { + e.printStackTrace(); + } + return position; + } + + /** + * Remove the blanks at the end of each lines + * @param start the starting position in the doc + * @param end the ending position in the doc + * @return the new positions of the selected text + */ + public int[] removeTrailingWhite(int start, int end) { + int nfirst = elem.getElementIndex(start); + int nlast = elem.getElementIndex(end); + int sstart = elem.getElement(nfirst).getStartOffset(); + int eend = elem.getElement(nlast).getEndOffset() - 1; + int[] ret = new int[2]; + ret[0] = start; + + try { + String str = doc.getText(sstart, eend - sstart); + str = str.replaceAll(REGEXP_WHITES_AT_EOL, "\n"); + int len = str.length(); + str = str.replaceFirst(REGEXP_WHITES_AT_END, ""); + len = len - str.length(); + + ret[1] = sstart + str.length() - (eend - end - len - 1); + + doc.replace(sstart, eend - sstart, str, null); + } catch (BadLocationException e) { + e.printStackTrace(); + return null; + } + + return ret; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/AboutAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/AboutAction.java new file mode 100755 index 000000000..27573376f --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/AboutAction.java @@ -0,0 +1,58 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2009 - DIGITEO - Vincent COUVERT + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.utils.ScilabAboutBox; +import org.scilab.modules.scinotes.SciNotes; + +/** + * Display about box for the text editor + * @author Bruno JOFRET + * @author Vincent COUVERT + */ +public final class AboutAction extends DefaultAction { + + private static final long serialVersionUID = -8172282717877209957L; + + /** + * Constructor + * @param name the name of the action + * @param editor associated editor + */ + public AboutAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Menu created for "Help menu" + * @param label label of the menu + * @param editor associated editor + * @param key KeyStroke + * @return the menu + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new AboutAction(label, editor), key); + } + + /** + * Action !! + * @see org.scilab.modules.graph.actions.DefaultAction#doAction() + */ + public void doAction() { + ScilabAboutBox.displayAndWait(); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ActivateHelpOnTypingForKeywordsAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ActivateHelpOnTypingForKeywordsAction.java new file mode 100755 index 000000000..bb05ee26d --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ActivateHelpOnTypingForKeywordsAction.java @@ -0,0 +1,68 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.HelpOnTypingManager; + +/** + * ActivateHelpOnTypingForKeywordsAction Class + * @author Calixte DENIZET + * + */ +public final class ActivateHelpOnTypingForKeywordsAction extends DefaultCheckAction { + + private static final long serialVersionUID = 3793710651553964430L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ActivateHelpOnTypingForKeywordsAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + HelpOnTypingManager.getInstance().enableKeywords(getState()); + SciNotes.activateHelpOnTyping(); + } + + /** + * createCheckBoxMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return CheckBoxMenuItem + */ + public static CheckBoxMenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + final CheckBoxMenuItem cb = createCheckBoxMenu(label, null, new ActivateHelpOnTypingForKeywordsAction(label, editor), key); + cb.setChecked(HelpOnTypingManager.getInstance().isKeywordsActive()); + ((JCheckBoxMenuItem) cb.getAsSimpleCheckBoxMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + cb.setChecked(HelpOnTypingManager.getInstance().isKeywordsActive()); + } + }); + + return cb; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ActivateHelpOnTypingForOpenersAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ActivateHelpOnTypingForOpenersAction.java new file mode 100755 index 000000000..e747cdc00 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ActivateHelpOnTypingForOpenersAction.java @@ -0,0 +1,68 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.HelpOnTypingManager; + +/** + * ActivateHelpOnTypingForOpenersAction Class + * @author Calixte DENIZET + * + */ +public final class ActivateHelpOnTypingForOpenersAction extends DefaultCheckAction { + + private static final long serialVersionUID = 7522390935632696429L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ActivateHelpOnTypingForOpenersAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + HelpOnTypingManager.getInstance().enableOpeners(getState()); + SciNotes.activateHelpOnTyping(); + } + + /** + * createCheckBoxMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return CheckBoxMenuItem + */ + public static CheckBoxMenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + final CheckBoxMenuItem cb = createCheckBoxMenu(label, null, new ActivateHelpOnTypingForOpenersAction(label, editor), key); + cb.setChecked(HelpOnTypingManager.getInstance().isOpenersActive()); + ((JCheckBoxMenuItem) cb.getAsSimpleCheckBoxMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + cb.setChecked(HelpOnTypingManager.getInstance().isOpenersActive()); + } + }); + + return cb; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CCloseTabInNewWindowAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CCloseTabInNewWindowAction.java new file mode 100755 index 000000000..d2fbd0407 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CCloseTabInNewWindowAction.java @@ -0,0 +1,54 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * Display about box for the text editor + * @author Calixte DENIZET + */ +public final class CCloseTabInNewWindowAction extends DefaultAction { + + private static final long serialVersionUID = 5238253626333724452L; + + /** + * Constructor + * @param name the name of the action + * @param editor associated editor + */ + public CCloseTabInNewWindowAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CCloseTabInNewWindowAction(label, editor), key); + } + + /** + * Action + */ + public void doAction() { + SciNotes.cloneAndCloseCurrentTab(getEditor(), true); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CapitalizeAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CapitalizeAction.java new file mode 100755 index 000000000..f266ae660 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CapitalizeAction.java @@ -0,0 +1,138 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.StringTokenizer; + +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.CompoundUndoManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * CapitalizeAction Class + * @author Calixte DENIZET + */ +public final class CapitalizeAction extends DefaultAction { + + private static final long serialVersionUID = 1531881688147993338L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CapitalizeAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + String str; + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + + if (start == end) { + try { + String letter = doc.getText(start, 1); + char c = letter.charAt(0); + if (Character.isUpperCase(c)) { + str = letter.toLowerCase(); + } else { + str = letter.toUpperCase(); + } + doc.mergeEditsBegin(); + doc.getUndoManager().enableOneShot(true); + sep.select(start, start + 1); + sep.replaceSelection(str); + doc.mergeEditsEnd(); + doc.getUndoManager().enableOneShot(false); + } catch (BadLocationException e) { } + } else { + str = sep.getSelectedText(); + boolean nonLetter = true; + char[] buf = str.toCharArray(); + for (int i = 0; i < buf.length; i++) { + char c = buf[i]; + if (Character.isLetter(c)) { + if (nonLetter) { + if (Character.isLowerCase(c)) { + buf[i] = Character.toUpperCase(c); + } else { + buf[i] = Character.toLowerCase(c); + } + nonLetter = false; + } + } else { + nonLetter = true; + } + } + + doc.mergeEditsBegin(); + sep.replaceSelection(new String(buf)); + sep.select(start, end); + doc.mergeEditsEnd(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + StringTokenizer token = new StringTokenizer(label, ";\uff1b"); + final String label1 = token.nextToken(); + final String label2 = token.nextToken(); + return createMenu(label1, label2, editor, key, new CapitalizeAction(label1, editor)); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @param hoka the HelpOnKeyword action + * @return MenuItem + */ + protected static MenuItem createMenu(final String label1, final String label2, final SciNotes editor, KeyStroke key, final CapitalizeAction hoka) { + final MenuItem menuitem = createMenu(label1, null, hoka, key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + String select = editor.getTextPane().getSelectedText(); + if (select == null) { + menuitem.setText(label2); + } else { + menuitem.setText(label1); + } + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAction.java new file mode 100755 index 000000000..07523736b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAction.java @@ -0,0 +1,66 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * CloseAction Class + * @author Bruno JOFRET + * + */ +public final class CloseAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 3575152401442746355L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CloseAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + SciNotes ed = getEditor(); + ed.closeTabAt(ed.getTabPane().getSelectedIndex()); + + // Close the last opened file create a new file named "Untitled 1" + if (ed.getTabPane().getTabCount() == 0) { + ed.addEmptyTab(); + ConfigSciNotesManager.saveToOpenFiles(ed.getTextPane().getName(), ed, ed.getTextPane()); + } + } + + /** + * CreateMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CloseAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAllAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAllAction.java new file mode 100755 index 000000000..5fbc3e7e8 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAllAction.java @@ -0,0 +1,70 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * CloseAllAction Class + * @author Allan CORNET + * + */ +public final class CloseAllAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 7134703185408271944L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CloseAllAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + SciNotes ed = getEditor(); + while (ed.getTabPane().getTabCount() != 0) { + if (!ed.closeTabAt(ed.getTabPane().getSelectedIndex())) { + return; + } + } + + // Close the last opened file create a new file named "Untitled 1" + if (ed.getTabPane().getTabCount() == 0) { + ed.addEmptyTab(); + ConfigSciNotesManager.saveToOpenFiles(ed.getTextPane().getName(), ed, ed.getTextPane()); + } + } + + /** + * Create menu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CloseAllAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAllButThisAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAllButThisAction.java new file mode 100755 index 000000000..569d60baa --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CloseAllButThisAction.java @@ -0,0 +1,77 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * CloseAllButThisAction Class + * @author Allan CORNET + * + */ +public final class CloseAllButThisAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -9052217229357472945L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CloseAllButThisAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + SciNotes ed = getEditor(); + int nbTabCount = ed.getTabPane().getTabCount(); + boolean bContinue = true; + if (nbTabCount > 1) { + while ((ed.getTabPane().getTabCount() != 1) & (bContinue)) { + int currentIndex = ed.getTabPane().getSelectedIndex(); + if (currentIndex != 0) { + bContinue = ed.closeTabAt(0); + } else { + bContinue = ed.closeTabAt(1); + } + } + } + + // Close the last opened file create a new file named "Untitled 1" + if (ed.getTabPane().getTabCount() == 0) { + ed.addEmptyTab(); + ConfigSciNotesManager.saveToOpenFiles(ed.getTextPane().getName(), ed, ed.getTextPane()); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CloseAllButThisAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CodeNavigatorAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CodeNavigatorAction.java new file mode 100755 index 000000000..6fb9cc8d7 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CodeNavigatorAction.java @@ -0,0 +1,68 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.tabfactory.CodeNavigatorTab; +import org.scilab.modules.scinotes.utils.NavigatorWindow; + +/** + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +@SuppressWarnings("serial") +public final class CodeNavigatorAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CodeNavigatorAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return createMenu + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CodeNavigatorAction(label, editor), key); + } + + /** + * Action !! + */ + public void doAction() { + getEditor().addNavigator(); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new CodeNavigatorAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CommentAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CommentAction.java new file mode 100755 index 000000000..12f294f4c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CommentAction.java @@ -0,0 +1,81 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.CommentManager; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * CommentAction Class + * @author Bruno JOFRET + * + */ +public final class CommentAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -7258307088402814986L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CommentAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + int pos = sep.getCaretPosition(); + CommentManager com = sep.getCommentManager(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + + doc.mergeEditsBegin(); + if (start == end) { + com.commentLines(start, start); + } else { + int[] ret = com.commentLines(start, end); + if (ret != null) { + if (pos == start) { + sep.select(ret[1], ret[0]); + } else { + sep.select(ret[0], ret[1]); + } + } + } + doc.mergeEditsEnd(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CommentAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopyAsHTMLAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopyAsHTMLAction.java new file mode 100755 index 000000000..9ab9e9204 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopyAsHTMLAction.java @@ -0,0 +1,215 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.im.InputContext; +import java.io.IOException; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import javax.swing.TransferHandler; + +import org.scilab.modules.jvm.LoadClassPath; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.HTMLCodeConverter; + +/** + * CopyAsHTMLAction Class + * @author Calixte Denizet + */ +public class CopyAsHTMLAction extends DefaultAction { + + private static final long serialVersionUID = 5363720520521282071L; + + protected boolean printLineNumber; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CopyAsHTMLAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + if (!getEditor().getTextPane().copyColumnSelectionInClipBoard()) { + String selection = getEditor().getTextPane().getSelectedText(); + if (selection != null) { + HTMLSelection sel = new HTMLSelection(getEditor().getTextPane(), selection, printLineNumber); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, sel); + } + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return createMenu + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CopyAsHTMLAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new CopyAsHTMLAction(tooltip, editor)); + } + + /** + * Inner class to handle HTML selectoin + */ + public static class HTMLSelection implements Transferable, ClipboardOwner { + + private DataFlavor htmlFlavor; + private String data; + private boolean printLineNumber; + private ScilabEditorPane pane; + private boolean codeConverterLoaded; + + /** + * Default constructor + * @param data the data to copy + */ + HTMLSelection(ScilabEditorPane pane, String data, boolean printLineNumber) { + this.data = data; + this.printLineNumber = printLineNumber; + this.pane = pane; + try { + htmlFlavor = new DataFlavor("text/html;class=java.lang.String"); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + } + + /** + * {@inheritDoc} + */ + public Object getTransferData(DataFlavor flavor) { + Object ret = null; + if (flavor.equals(htmlFlavor)) { + if (!codeConverterLoaded) { + LoadClassPath.loadOnUse("copyAsHTMLinScinotes"); + codeConverterLoaded = true; + } + ret = new HTMLCodeConverter(pane).convert(data, printLineNumber); + } else if (flavor.equals(DataFlavor.stringFlavor)) { + ret = data; + } + + return ret; + } + + /** + * {@inheritDoc} + */ + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] {htmlFlavor, DataFlavor.stringFlavor}; + } + + /** + * {@inheritDoc} + */ + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.equals(htmlFlavor) || flavor.equals(DataFlavor.stringFlavor); + } + + /** + * {@inheritDoc} + */ + public void lostOwnership(Clipboard clipboard, Transferable contents) { } + } + + /** + * Inner class to handle the HTML transfers + */ + public static class HTMLTransferHandler extends TransferHandler { + + private static final long serialVersionUID = -5089826958820112637L; + + /** + * Default constructor + */ + public HTMLTransferHandler() { } + + /** + * {@inheritDoc} + */ + protected Transferable createTransferable(JComponent c) { + ScilabEditorPane pane = (ScilabEditorPane) c; + String selection = pane.getSelectedText(); + if (selection != null) { + return new HTMLSelection(pane, selection, false); + } else { + return null; + } + } + + /** + * {@inheritDoc} + */ + public boolean importData(JComponent c, Transferable t) { + if (c instanceof ScilabEditorPane) { + DataFlavor[] flavors = t.getTransferDataFlavors(); + if (flavors != null) { + int i = 0; + for (; i < flavors.length; i++) { + if (flavors[i].equals(DataFlavor.stringFlavor)) { + break; + } + } + if (i != flavors.length) { + InputContext ic = c.getInputContext(); + if (ic != null) { + ic.endComposition(); + } + try { + String data = (String) t.getTransferData(DataFlavor.stringFlavor); + ((ScilabEditorPane) c).replaceSelection(data); + return true; + } catch (UnsupportedFlavorException e) { } + catch (IOException ex) { } + } + } + } + return false; + } + + /** + * {@inheritDoc} + */ + public int getSourceActions(JComponent c) { + return COPY_OR_MOVE; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopyAsHTMLWithLineNumberAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopyAsHTMLWithLineNumberAction.java new file mode 100755 index 000000000..9468de737 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopyAsHTMLWithLineNumberAction.java @@ -0,0 +1,60 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * CopyAsHTMLWithLineNumberAction Class + * @author Calixte Denizet + */ +public class CopyAsHTMLWithLineNumberAction extends CopyAsHTMLAction { + + private static final long serialVersionUID = -8643739654819519110L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CopyAsHTMLWithLineNumberAction(String name, SciNotes editor) { + super(name, editor); + printLineNumber = true; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return createMenu + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CopyAsHTMLWithLineNumberAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new CopyAsHTMLWithLineNumberAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopySelectionInNewTabAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopySelectionInNewTabAction.java new file mode 100755 index 000000000..aac5a66ad --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CopySelectionInNewTabAction.java @@ -0,0 +1,71 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * CopySelectionInNewTabAction class + * @author Calixte DENIZET + */ +public final class CopySelectionInNewTabAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 320938663765236236L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CopySelectionInNewTabAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + String selection = getEditor().getTextPane().getSelectedText(); + SciNotes.scinotesWithText(selection); + } + + /** + * createMenu + * @param label label of the menu + * @param editor scinotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + final MenuItem menuitem = createMenu(label, null, new CopySelectionInNewTabAction(label, editor), key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + String selection = editor.getTextPane().getSelectedText(); + menuitem.setEnabled(selection != null); + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CutAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CutAction.java new file mode 100755 index 000000000..6be424630 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/CutAction.java @@ -0,0 +1,85 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Toolkit; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * CutAction Class + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public final class CutAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -4831313579986185630L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public CutAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + doc.mergeEditsBegin(); + if (!getEditor().getTextPane().copyColumnSelectionInClipBoard() || !getEditor().getTextPane().removeColumnSelection()) { + String selection = getEditor().getTextPane().getSelectedText(); + if (selection != null) { + CopyAsHTMLAction.HTMLSelection sel = new CopyAsHTMLAction.HTMLSelection(getEditor().getTextPane(), selection, false); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, sel); + getEditor().getTextPane().replaceSelection(""); + } + } + doc.mergeEditsEnd(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new CutAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new CutAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DefaultAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DefaultAction.java new file mode 100755 index 000000000..e16ad8dee --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DefaultAction.java @@ -0,0 +1,123 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.event.ActionListener; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; + +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem; +import org.scilab.modules.gui.events.callback.CommonCallBack; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menuitem.ScilabMenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * Default action in SciNotes + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public class DefaultAction extends CommonCallBack { + + private static final long serialVersionUID = 3597772070169671017L; + + private final SciNotes editor; + + /** + * Constructor + * @param editor associated SciNotes instance + */ + private DefaultAction(SciNotes editor) { + super(SciNotesMessages.DEFAULT + SciNotesMessages.DOTS); + this.editor = editor; + } + + /** + * Constructor + * @param label action name + * @param editor associated editor + */ + protected DefaultAction(String label, SciNotes editor) { + super(label); + this.editor = editor; + } + + /** + * Get associated editor + * @return editor instance + */ + public SciNotes getEditor() { + return editor; + } + + /** + * Create a button for a tool bar + * @param title tooltip for the button + * @param icon image icon + * @param listener action listener + * @return the button + */ + protected static JButton createButton(String title, String icon, ActionListener listener) { + JButton button = new JButton(); + button.addActionListener(listener); + button.setToolTipText(title); + if (icon == null) { + button.setText(title); + } else { + button.setIcon(new ImageIcon(FindIconHelper.findIcon(icon))); + } + return button; + } + + /** + * Create a menu for a menu bar + * @param title label for the menu + * @param icon image icon + * @param listener action listener + * @param keyStroke menu shortcut + * @return the button + */ + protected static MenuItem createMenu(String title, String icon, DefaultAction listener, KeyStroke keyStroke) { + MenuItem menu = ScilabMenuItem.createMenuItem(); + menu.setCallback(listener); + menu.setText(title); + + if (keyStroke != null) { + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).setAccelerator(keyStroke); + } + + return menu; + } + + /** + * Default action + */ + public void doAction() { + JOptionPane.showMessageDialog(getEditor(), "Not Implemented Now !!!", null, JOptionPane.ERROR_MESSAGE); + } + + /** + * Default action + */ + @Override + public void callBack() { + doAction(); + } + +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DefaultCheckAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DefaultCheckAction.java new file mode 100755 index 000000000..02fa26e3a --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DefaultCheckAction.java @@ -0,0 +1,149 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.bridge.checkboxmenuitem.SwingScilabCheckBoxMenuItem; +import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem; +import org.scilab.modules.gui.checkboxmenuitem.SimpleCheckBoxMenuItem; +import org.scilab.modules.gui.events.callback.CommonCallBack; +import org.scilab.modules.gui.menu.SimpleMenu; +import org.scilab.modules.gui.menuitem.SimpleMenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * DefaultCheckAction Class + * @author Bruno JOFRET + * + */ +public class DefaultCheckAction extends SwingScilabCheckBoxMenuItem implements CheckBoxMenuItem, ActionListener { + /** + * serialVersionUID + */ + private static final long serialVersionUID = 5618123082228356437L; + private SciNotes editorBackup; + + /** + * Constructor + * @param editor SciNotes + */ + @SuppressWarnings("serial") + public DefaultCheckAction(SciNotes editor) { + super(); + setText(SciNotesMessages.DEFAULT + SciNotesMessages.DOTS); + setState(true); + editorBackup = editor; + + setCallback(new CommonCallBack(SciNotesMessages.DEFAULT + SciNotesMessages.DOTS) { + public void callBack() { + doAction(); + } + + public void actionPerformed(ActionEvent e) { + callBack(); + } + }); + } + + /** + * + * @param label label (string) + * @param editor SciNotes + */ + @SuppressWarnings("serial") + protected DefaultCheckAction(String label, SciNotes editor) { + super(); + setText(label); + setState(true); + editorBackup = editor; + setCallback(new CommonCallBack(SciNotesMessages.DEFAULT + SciNotesMessages.DOTS) { + public void callBack() { + doAction(); + } + + public void actionPerformed(ActionEvent e) { + callBack(); + } + }); + } + + /** + * get Editor + * @return SciNotes + */ + public SciNotes getEditor() { + return editorBackup; + } + + /** + * doAction + */ + public void doAction() { + JOptionPane.showMessageDialog(getEditor(), "Not Implemented Now !!! (state = " + getState() + ")", null, JOptionPane.ERROR_MESSAGE); + } + + /** + * actionPerformed + * @param arg0 ActionEvent + */ + public void actionPerformed(ActionEvent arg0) { + doAction(); + } + + /** + * createCheckBoxMenu + * @param title String + * @param icon String + * @param defaultCheckAction DefaultCheckAction + * @param keyStroke KeyStroke + * @return CheckBoxMenuItem + */ + protected static CheckBoxMenuItem createCheckBoxMenu(String title, String icon, DefaultCheckAction defaultCheckAction, KeyStroke keyStroke) { + defaultCheckAction.setText(title); + defaultCheckAction.setChecked(false); + if (keyStroke != null) { + ((SwingScilabCheckBoxMenuItem) defaultCheckAction.getAsSimpleCheckBoxMenuItem()).setAccelerator(keyStroke); + } + return defaultCheckAction; + } + + /** + * getAsSimpleCheckBoxMenuItem + * @return SimpleCheckBoxMenuItem + */ + public SimpleCheckBoxMenuItem getAsSimpleCheckBoxMenuItem() { + return this; + } + + /** + * getAsSimpleMenuItem + * @return SimpleMenuItem + */ + public SimpleMenuItem getAsSimpleMenuItem() { + return null; + } + + /** + * getAsSimpleMenu + * @return SimpleMenu + */ + public SimpleMenu getAsSimpleMenu() { + return null; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DeleteAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DeleteAction.java new file mode 100755 index 000000000..3c118d9d6 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DeleteAction.java @@ -0,0 +1,66 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; +import javax.swing.text.DefaultEditorKit; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.SciNotes; + +/** + * Delete action + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public final class DeleteAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -1818764947112443369L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public DeleteAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * DoAction + */ + public void doAction() { + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + doc.mergeEditsBegin(); + if (!getEditor().getTextPane().removeColumnSelection()) { + getEditor().getTextPane().getActionMap().get(DefaultEditorKit.deleteNextCharAction).actionPerformed(null); + } + doc.mergeEditsEnd(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new DeleteAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DoubleQuoteStringAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DoubleQuoteStringAction.java new file mode 100755 index 000000000..8e21b589b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/DoubleQuoteStringAction.java @@ -0,0 +1,124 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.IOException; + +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.CompoundUndoManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabLexer; +import org.scilab.modules.scinotes.ScilabLexerConstants; + +/** + * DoubleQuoteStringAction Class + * @author Calixte DENIZET + */ +public final class DoubleQuoteStringAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public DoubleQuoteStringAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + doc.getUndoManager().enableOneShot(true); + doc.mergeEditsBegin(); + doubleQuoteString(doc); + doc.mergeEditsEnd(); + doc.getUndoManager().enableOneShot(false); + } + + /** + * Replace the strings simply quoted by double quoted strings + * @param doc the documen + */ + public static void doubleQuoteString(ScilabDocument doc) { + StringBuffer buffer = new StringBuffer(128); + ScilabLexer lexer = doc.createLexer(false); + Element elem = doc.getDefaultRootElement(); + Element line; + int lastLine = elem.getElementIndex(doc.getLength()); + int tok; + + try { + for (int i = 0; i <= lastLine; i++) { + line = elem.getElement(i); + lexer.setRange(line.getStartOffset(), line.getEndOffset()); + do { + tok = lexer.scan(); + if (ScilabLexerConstants.isString(tok)) { + buffer.append(doc.getText(lexer.start + lexer.yychar(), lexer.yylength())); + } else if (buffer.length() > 0) { + boolean modified = false; + int len = buffer.length(); + if (buffer.charAt(0) == '\'') { + buffer.replace(0, 1, "\""); + modified = true; + } + if (len > 1 && buffer.charAt(len - 1) == '\'') { + buffer.replace(len - 1, len, "\""); + modified = true; + } + if (modified) { + int start = lexer.start + lexer.yychar() - len; + doc.replace(start, len, buffer.toString(), null); + } + buffer.setLength(0); + } + } while (tok != ScilabLexerConstants.EOF); + } + } catch (Exception e) { + System.err.println(e); + } + } + + /** + * @return an action to replace single quoted strings by double quoted ones in a document + */ + public static SciNotes.ActionOnDocument getActionOnDocument() { + return new SciNotes.ActionOnDocument() { + public void actionOn(ScilabDocument doc) throws IOException { + doubleQuoteString(doc); + } + }; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new DoubleQuoteStringAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EncodingAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EncodingAction.java new file mode 100755 index 000000000..980f1b2f6 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EncodingAction.java @@ -0,0 +1,386 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.UnsupportedCharsetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import javax.swing.ButtonGroup; +import javax.swing.ImageIcon; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.EditorKit; + +import org.scilab.modules.commons.ScilabConstants; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * EncodingAction Class + * @author Bruno JOFRET + * @author Calixte DENIZET + * + */ +public class EncodingAction extends DefaultCheckAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -5421313717126859924L; + + private static final String CHECKICON = ScilabConstants.SCI.getPath() + "/modules/gui/images/icons/check-icon.png"; + + private static Map<String, String> encodings = new HashMap<String, String>(); + private static Map<String, List<String>> language = new HashMap<String, List<String>>(); + private static JRadioButtonMenuItem[] radioTypes; + private static Menu[] menuLang; + + static { + encodings.put("x-MacArabic", "Arabic"); + encodings.put("x-MacCentralEurope", "Central European"); + encodings.put("x-MacCroatian", "Central European"); + encodings.put("x-MacCyrillic", "Cyrillic"); + encodings.put("x-MacGreek", "Greek"); + encodings.put("x-MacHebrew", "Hebrew"); + encodings.put("x-MacIceland", "Western European"); + encodings.put("x-MacRoman", "Western European"); + encodings.put("x-MacRomania", "Central European"); + encodings.put("x-MacThai", "Thai"); + encodings.put("x-MacTurkish", "Turkish"); + encodings.put("x-MacUkraine", "Cyrillic"); + encodings.put("ASMO-708", "Arabic"); + encodings.put("cp866", "Cyrillic"); + encodings.put("windows-874", "Thai"); + encodings.put("shift_jis", "Japanese"); + encodings.put("gb2312", "Chinese Simplified"); + encodings.put("ks_c_5601-1987", "Korean"); + encodings.put("big5", "Chinese Traditional"); + encodings.put("utf-16", "Unicode"); + encodings.put("windows-1250", "Central European"); + encodings.put("windows-1251", "Cyrillic"); + encodings.put("windows-1252", "Western European"); + encodings.put("windows-1253", "Greek"); + encodings.put("windows-1254", "Turkish"); + encodings.put("windows-1255", "Hebrew"); + encodings.put("windows-1256", "Arabic"); + encodings.put("windows-1257", "Baltic"); + encodings.put("windows-1258", "Vietnamese"); + encodings.put("Johab", "Korean"); + encodings.put("utf-32", "Unicode"); + encodings.put("utf-32BE", "Unicode"); + encodings.put("us-ascii", "US-ASCII"); + encodings.put("koi8-r", "Cyrillic"); + encodings.put("EUC-JP", "Japanese"); + encodings.put("koi8-u", "Cyrillic"); + encodings.put("iso-8859-1", "Western European"); + encodings.put("iso-8859-2", "Central European"); + encodings.put("iso-8859-3", "Latin"); + encodings.put("iso-8859-4", "Baltic"); + encodings.put("iso-8859-5", "Cyrillic"); + encodings.put("iso-8859-6", "Arabic"); + encodings.put("iso-8859-7", "Greek"); + encodings.put("iso-8859-8", "Hebrew"); + encodings.put("iso-8859-9", "Turkish"); + encodings.put("iso-8859-13", "Estonian"); + encodings.put("iso-8859-15", "Latin"); + encodings.put("iso-2022-jp", "Japanese"); + encodings.put("csISO2022JP", "Japanese"); + encodings.put("iso-2022-kr", "Korean"); + encodings.put("euc-jp", "Japanese"); + encodings.put("EUC-CN", "Chinese Simplified"); + encodings.put("euc-kr", "Korean"); + encodings.put("GB18030", "Chinese Simplified"); + encodings.put("utf-8", "Unicode"); + } + + private String encoding; + + /** + * Constructor + * @param encodingName Encoding Name + * @param editor SciNotes + */ + public EncodingAction(String encodingName, SciNotes editor) { + super(encodingName, editor); + encoding = encodingName; + } + + /** + * Clean + */ + public static void close() { + radioTypes = null; + menuLang = null; + } + + /** + * createRadioButtonMenuItem + * @param editor SciNotes + * @return JRadioButtonMenuItem + */ + public JRadioButtonMenuItem createRadioButtonMenuItem(SciNotes editor) { + JRadioButtonMenuItem radio = new JRadioButtonMenuItem(encoding); + radio.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + doAction(); + } + }); + + return radio; + } + + /** + * createEncodingSubMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return a Menu + */ + public static Menu createMenu(String label, SciNotes editor, KeyStroke key) { + Menu encodingTypeMenu = ScilabMenu.createMenu(); + encodingTypeMenu.setText(label); + + Map<String, List<String>> languages = getEncodings(); + Iterator<String> iter = languages.keySet().iterator(); + int size = 0; + while (iter.hasNext()) { + size += languages.get(iter.next()).size(); + } + + if (radioTypes == null) { + radioTypes = new JRadioButtonMenuItem[size]; + menuLang = new Menu[languages.size()]; + } + + ButtonGroup group = new ButtonGroup(); + + iter = languages.keySet().iterator(); + int psize = 0; + int k = 0; + while (iter.hasNext()) { + String lang = iter.next(); + List<String> encodingList = languages.get(lang); + menuLang[k] = ScilabMenu.createMenu(); + menuLang[k].setText(lang); + encodingTypeMenu.add(menuLang[k]); + for (int i = 0; i < encodingList.size(); i++) { + radioTypes[psize + i] = (new EncodingAction(encodingList.get(i), editor)).createRadioButtonMenuItem(editor); + group.add(radioTypes[psize + i]); + ((JMenu) menuLang[k].getAsSimpleMenu()).add(radioTypes[psize + i]); + + if (encodingList.get(i).equalsIgnoreCase(Charset.defaultCharset().toString())) { + radioTypes[psize + i].setSelected(true); + } + } + psize += encodingList.size(); + k++; + } + + return encodingTypeMenu; + } + + public static Set<String> getSupportedEncodings() { + return encodings.keySet(); + } + + /** + * Update the selected item in the encoding pull down menu of the document. + * @param scilabDocument the document for which the encoding menu should + * be updated + */ + public static void updateEncodingMenu(ScilabDocument scilabDocument) { + if (radioTypes != null) { + for (int i = 0; i < radioTypes.length; i++) { + if (scilabDocument.getEncoding().equalsIgnoreCase(radioTypes[i].getText())) { + radioTypes[i].setSelected(true); + updateIcon(radioTypes[i].getText()); + return; + } + } + } + } + + /** + * getEncodings + * @return Map : Language -> {enc1, enc2, ...} + */ + public static Map<String, List<String>> getEncodings() { + if (!language.isEmpty()) { + return language; + } + + Set<String> keys = encodings.keySet(); + Iterator<String> iterator = keys.iterator(); + while (iterator.hasNext()) { + String enc = iterator.next(); + try { + Charset.forName(enc); + String lang = encodings.get(enc); + if (!language.containsKey(lang)) { + language.put(lang, new ArrayList<String>()); + } + + language.get(lang).add(enc); + } catch (IllegalCharsetNameException e) { + encodings.remove(enc); + } catch (UnsupportedCharsetException e) { + encodings.remove(enc); + } + } + + language = new TreeMap<String, List<String>>(language); + return language; + } + + /** + * doAction + */ + public void doAction() { + boolean isSuccess = false; + + ScilabDocument styleDocument = ((ScilabDocument) getEditor().getTextPane().getDocument()); + + if (styleDocument.isContentModified()) { + /* File modified */ + if (getEditor().getTextPane().getName() != null) { + /* Not untitled */ + switch (ScilabModalDialog.show(getEditor(), + SciNotesMessages.MODIFICATIONS_WILL_BE_LOST, SciNotesMessages.CONTINUE, + IconType.QUESTION_ICON, ButtonType.YES_NO)) { + case YES_OPTION : //Yes, continue + break; + case NO_OPTION ://No, exit + //Back to previous menu checked + updateEncodingMenu(styleDocument); + return; + default: + break; + } + } + } + + // Avoid modifications to be saved + styleDocument.setUpdater(false); + boolean indentMode = styleDocument.getAutoIndent(); + styleDocument.setAutoIndent(false); + + styleDocument.setEncoding(encoding); + //ConfigSciNotesManager.saveDefaultEncoding(encoding); + + //Update the menu + updateIcon(encoding); + + // If file associated then reload + EditorKit editorKit = getEditor().getEditorKit(); + String fileName = getEditor().getTextPane().getName(); + + FileInputStream fis = null; + InputStreamReader isr = null; + BufferedReader br = null; + + try { + if (fileName != null) { + File file = new File(getEditor().getTextPane().getName()); + if (file.exists()) { + if (styleDocument.getLength() > 0) { + styleDocument.getUndoManager().discardAllEdits(); + styleDocument.disableUndoManager(); + styleDocument.remove(0, styleDocument.getLength()); + + fis = new FileInputStream(file); + isr = new InputStreamReader(fis, encoding); + br = new BufferedReader(isr); + editorKit.read(br, styleDocument, 0); + + styleDocument.enableUndoManager(); + } + } + } + isSuccess = true; + } catch (UnsupportedEncodingException e) { + isSuccess = false; + } catch (FileNotFoundException e) { + isSuccess = false; + } catch (IOException e) { + isSuccess = false; + } catch (BadLocationException e) { + isSuccess = false; + } finally { + try { + if (fis != null) { + fis.close(); + } + if (isr != null) { + isr.close(); + } + if (br != null) { + br.close(); + } + } catch (IOException e) { } + } + + /* Allow changes to be saved */ + styleDocument.setAutoIndent(indentMode); + styleDocument.setUpdater(true); + + styleDocument.setContentModified(false); + // changing such a property dicards undo + styleDocument.getUndoManager().discardAllEdits(); + if (!isSuccess) { + ScilabModalDialog.show(getEditor(), SciNotesMessages.COULD_NOT_CONVERT_FILE, + SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + } + + /** + * Add a check-icon near the current used language + * @param enc the actual encoding + */ + private static void updateIcon(String enc) { + String lang = encodings.get(enc); + for (int i = 0; i < menuLang.length; i++) { + if (((JMenu) menuLang[i].getAsSimpleMenu()).getIcon() != null) { + ((JMenu) menuLang[i].getAsSimpleMenu()).setIcon(null); + } + if (menuLang[i].getText().equals(lang)) { + ((JMenu) menuLang[i].getAsSimpleMenu()).setIcon(new ImageIcon(CHECKICON)); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EndOfLineAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EndOfLineAction.java new file mode 100755 index 000000000..6fc6c74bf --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EndOfLineAction.java @@ -0,0 +1,199 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.ButtonGroup; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * Class EndOfLineAction + * @author Allan CORNET + * + */ +public class EndOfLineAction extends DefaultCheckAction { + + private static final String EOL_LINUX = "\n"; + private static final String EOL_MACOS = "\r"; + private static final String EOL_WINDOWS = "\r\n"; + private static final String LINE_SEPARATOR = "line.separator"; + + private static JRadioButtonMenuItem[] radioEolTypes; + + /** + * generated serialVersionUID + */ + private static final long serialVersionUID = 7147038540238271944L; + + /* default */ + private String eolMenuLabel = SciNotesMessages.EOL_AUT0; + + /** + * Constructor + * @param eolName String + * @param editor SciNotes + */ + public EndOfLineAction(String eolName, SciNotes editor) { + super(eolName, editor); + eolMenuLabel = eolName; + } + + /** + * createRadioButtonMenuItem + * @param editor SciNotes + * @return JRadioButtonMenuItem + */ + public JRadioButtonMenuItem createRadioButtonMenuItem(SciNotes editor) { + JRadioButtonMenuItem radio = new JRadioButtonMenuItem(eolMenuLabel); + radio.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + doAction(); + } + }); + return radio; + } + + /** + * Clean + */ + public static void close() { + radioEolTypes = null; + } + + /** + * doAction + */ + public void doAction() { + ScilabDocument styleDocument = ((ScilabDocument) getEditor().getTextPane().getDocument()); + + // default + String newOel = System.getProperty(LINE_SEPARATOR); + + if (eolMenuLabel.compareToIgnoreCase(SciNotesMessages.EOL_AUT0) == 0) { + newOel = System.getProperty(LINE_SEPARATOR); + } else if (eolMenuLabel.compareToIgnoreCase(SciNotesMessages.EOL_LINUX) == 0) { + newOel = EOL_LINUX; + } else if (eolMenuLabel.compareToIgnoreCase(SciNotesMessages.EOL_MACOS) == 0) { + newOel = EOL_MACOS; + } else if (eolMenuLabel.compareToIgnoreCase(SciNotesMessages.EOL_WINDOWS) == 0) { + newOel = EOL_WINDOWS; + } + + if (styleDocument.getEOL().compareTo(newOel) != 0) { + styleDocument.setEOL(newOel); + styleDocument.setContentModified(true); + // changing such a property dicards undo + styleDocument.getUndoManager().discardAllEdits(); + getEditor().updateTabTitle(); + } + } + + /** + * create End Of Line sub Menu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return a Menu + */ + public static Menu createMenu(String label, SciNotes editor, KeyStroke key) { + String eolLinux = ScilabDocument.EOLUNIX; + String eolMacOs = ScilabDocument.EOLMAC; + String eolWindows = ScilabDocument.EOLWIN; + String defaultEolLabel = SciNotesMessages.EOL_LINUX; + + // selected by default O.S + String systemEolValue = System.getProperty(LINE_SEPARATOR); + + if (systemEolValue.compareTo(eolLinux) == 0) { + defaultEolLabel = SciNotesMessages.EOL_LINUX; + } + + if (systemEolValue.compareTo(eolWindows) == 0) { + defaultEolLabel = SciNotesMessages.EOL_WINDOWS; + } + + if (systemEolValue.compareTo(eolMacOs) == 0) { + defaultEolLabel = SciNotesMessages.EOL_MACOS; + } + + Menu eolTypeMenu = ScilabMenu.createMenu(); + eolTypeMenu.setText(label); + + radioEolTypes = new JRadioButtonMenuItem[3]; + ButtonGroup groupEol = new ButtonGroup(); + + radioEolTypes[0] = (new EndOfLineAction(SciNotesMessages.EOL_LINUX, editor)).createRadioButtonMenuItem(editor); + groupEol.add(radioEolTypes[0]); + ((JMenu) eolTypeMenu.getAsSimpleMenu()).add(radioEolTypes[0]); + + radioEolTypes[1] = (new EndOfLineAction(SciNotesMessages.EOL_WINDOWS, editor)).createRadioButtonMenuItem(editor); + groupEol.add(radioEolTypes[1]); + ((JMenu) eolTypeMenu.getAsSimpleMenu()).add(radioEolTypes[1]); + + radioEolTypes[2] = (new EndOfLineAction(SciNotesMessages.EOL_MACOS, editor)).createRadioButtonMenuItem(editor); + groupEol.add(radioEolTypes[2]); + ((JMenu) eolTypeMenu.getAsSimpleMenu()).add(radioEolTypes[2]); + + // selected menu + for (int k = 0; k < radioEolTypes.length; k++) { + if (radioEolTypes[k].getText().compareTo(defaultEolLabel) == 0) { + radioEolTypes[k].setSelected(true); + } + } + + return eolTypeMenu; + } + + + /** + * Update the selected item in the EOL pull down menu of the document. + * @param scilabDocument the document for which the End Of Line menu should + * be updated + */ + public static void updateEolMenu(ScilabDocument scilabDocument) { + String eolLinux = ScilabDocument.EOLUNIX; + String eolMacOs = ScilabDocument.EOLMAC; + String eolWindows = ScilabDocument.EOLWIN; + + String eolUsedLabel = SciNotesMessages.EOL_LINUX; + String eolUsed = scilabDocument.getEOL(); + + if (eolUsed.compareTo(eolLinux) == 0) { + eolUsedLabel = SciNotesMessages.EOL_LINUX; + } + + if (eolUsed.compareTo(eolMacOs) == 0) { + eolUsedLabel = SciNotesMessages.EOL_MACOS; + } + + if (eolUsed.compareTo(eolWindows) == 0) { + eolUsedLabel = SciNotesMessages.EOL_WINDOWS; + } + + for (int k = 0; k < radioEolTypes.length; k++) { + if (radioEolTypes[k].getText().compareTo(eolUsedLabel) == 0) { + radioEolTypes[k].setSelected(true); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EvaluateSelectionAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EvaluateSelectionAction.java new file mode 100755 index 000000000..270c53f28 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/EvaluateSelectionAction.java @@ -0,0 +1,99 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.StringTokenizer; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.console.ScilabConsole; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; + +import org.scilab.modules.history_manager.HistoryManagement; + +/** + * EvaluateSelectionAction class + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public final class EvaluateSelectionAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 320938663765236236L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public EvaluateSelectionAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + /* Will do the job as if it was copy / paste in scilab Console */ + ScilabEditorPane sep = getEditor().getTextPane(); + String selection = sep.getCodeToExecute(); + if (selection.compareTo("") != 0) { + StringTokenizer tokens = new StringTokenizer(selection, "\n"); + String[] lines = new String[tokens.countTokens()]; + int i = 0; + while (tokens.hasMoreTokens()) { + lines[i++] = tokens.nextToken(); + } + HistoryManagement.appendLinesToScilabHistory(lines, lines.length); + ScilabConsole.getConsole().getAsSimpleConsole().sendCommandsToScilab(selection, true, false); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor scinotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + StringTokenizer token = new StringTokenizer(label, ";\uff1b"); + final String label1 = token.nextToken(); + final String label2 = token.nextToken(); + final MenuItem menuitem = createMenu(label1, null, new EvaluateSelectionAction(label1, editor), key); + if (!ScilabConsole.isExistingConsole()) { // Only available in STD mode + ((JMenuItem) menuitem.getAsSimpleMenuItem()).setEnabled(false); + } + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + String select = editor.getTextPane().getSelectedText(); + if (select == null) { + menuitem.setText(label2); + } else { + menuitem.setText(label1); + } + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExecuteFileIntoScilabAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExecuteFileIntoScilabAction.java new file mode 100755 index 000000000..9109b3214 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExecuteFileIntoScilabAction.java @@ -0,0 +1,116 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.console.ScilabConsole; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * ExecuteFileIntoScilabAction Class + * @author Bruno JOFRET + * @author Allan CORNET + * @author Calixte DENIZET + * + */ +public class ExecuteFileIntoScilabAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -8625083632641564277L; + + protected boolean saveBefore; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ExecuteFileIntoScilabAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Execute the file into Scilab + * @param editor the Scilab editor + */ + protected void executeFile(SciNotes editor, String filePath) { + if (filePath == null) { + return; + } + + filePath = filePath.replaceAll("\"", "\"\""); + filePath = filePath.replaceAll("'", "''"); + if (filePath.compareTo("") != 0) { + String cmdToExec = "exec('" + filePath + "', -1)"; + try { + ScilabConsole.getConsole().getAsSimpleConsole().sendCommandsToScilab(cmdToExec, true, false); + } catch (NoClassDefFoundError e) { + /* This happens when SciNotes is launch as standalone (ie without + * Scilab) */ + ScilabModalDialog.show(editor, SciNotesMessages.COULD_NOT_FIND_CONSOLE); + } + } + } + + /** + * doAction + */ + public void doAction() { + SciNotes editor = getEditor(); + if (((ScilabDocument) getEditor().getTextPane().getDocument()).isContentModified()) { + if (saveBefore || ScilabModalDialog.show(getEditor(), SciNotesMessages.EXECUTE_WARNING, SciNotesMessages.EXECUTE_FILE_INTO_SCILAB, + IconType.WARNING_ICON, ButtonType.CANCEL_OR_SAVE_AND_EXECUTE) == AnswerOption.SAVE_EXECUTE_OPTION) { + if (editor.save(getEditor().getTabPane().getSelectedIndex(), true)) { + this.executeFile(editor, editor.getTextPane().getName()); + } + } + } else { + this.executeFile(editor, editor.getTextPane().getName()); + } + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new ExecuteFileIntoScilabAction(tooltip, editor)); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new ExecuteFileIntoScilabAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExitAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExitAction.java new file mode 100755 index 000000000..8efe6f05e --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExitAction.java @@ -0,0 +1,67 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * ExitAction class + * @author Bruno JOFRET + * + */ +public final class ExitAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -6434487252794798547L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ExitAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + doExit(getEditor()); + } + + /** + * doExit + * @param editor SciNotes + */ + public static void doExit(SciNotes editor) { + SciNotes.closeEditor(editor); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new ExitAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExportAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExportAction.java new file mode 100755 index 000000000..0ef127b25 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ExportAction.java @@ -0,0 +1,232 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Cursor; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser; +import org.scilab.modules.gui.filechooser.ScilabFileChooser; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.gui.utils.ConfigManager; +import org.scilab.modules.gui.utils.SciFileFilter; +import org.scilab.modules.jvm.LoadClassPath; +import org.scilab.modules.localization.Messages; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.CodeExporter; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * Class Export action for SciNotes + * @author Calixte DENIZET + */ +public class ExportAction extends DefaultAction { + + private static final long serialVersionUID = 7796680521955058413L; + + private static final String DOT = "."; + + private boolean codeConverterLoaded; + private File currentFile; + + /** + * Default constructor + * @param name the name of the action + * @param editor the editor + */ + public ExportAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Function doAction + */ + public void doAction() { + String extension = null; + String title = "Export"; + String path = ""; + + String initialDirectoryPath = path; + if (initialDirectoryPath == null) { + initialDirectoryPath = getEditor().getTextPane().getName(); + } + if (initialDirectoryPath == null) { + initialDirectoryPath = ConfigManager.getLastOpenedDirectory(); + } + + SciFileFilter pdfFilter = new SciFileFilter("*.pdf", null, 0); + SciFileFilter psFilter = new SciFileFilter("*.ps", null, 1); + SciFileFilter epsFilter = new SciFileFilter("*.eps", null, 2); + SciFileFilter rtfFilter = new SciFileFilter("*.rtf", null, 3); + + final SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser()); + + fileChooser.setInitialDirectory(ConfigManager.getLastOpenedDirectory()); + fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.setInitialDirectory(initialDirectoryPath); + fileChooser.setDialogTitle(Messages.gettext(title)); + fileChooser.setApproveButtonText(Messages.gettext(title)); + + // order is also important here + fileChooser.addChoosableFileFilter(pdfFilter); + fileChooser.addChoosableFileFilter(psFilter); + fileChooser.addChoosableFileFilter(epsFilter); + fileChooser.addChoosableFileFilter(rtfFilter); + + //select default file type + fileChooser.setFileFilter(pdfFilter); + fileChooser.setTitle(title); + + fileChooser.addPropertyChangeListener(JFileChooser.FILE_FILTER_CHANGED_PROPERTY, new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + Object val = e.getNewValue(); + if (val != null && (val instanceof SciFileFilter)) { + String filter = ((SciFileFilter) val).getDescription(); + String file = currentFile.getName(); + int dotpos = file.lastIndexOf("."); + if (dotpos != -1) { + file = file.substring(0, dotpos); + } + dotpos = filter.lastIndexOf("."); + if (dotpos != -1) { + filter = filter.substring(dotpos, filter.length() - 1); + } + fileChooser.setSelectedFile(new File(file + filter)); + } + } + }); + + fileChooser.addPropertyChangeListener(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY , new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + Object val = e.getNewValue(); + if (val != null && (val instanceof File)) { + currentFile = (File) val; + } + } + }); + + String name = getEditor().getTextPane().getName(); + if (name == null) { + name = ((ScilabDocument) getEditor().getTextPane().getDocument()).getFirstFunctionName(); + if (name == null) { + name = ""; + } + } + int dotpos = name.lastIndexOf("."); + if (dotpos != -1) { + name = name.substring(0, dotpos); + } + if (name != null) { + name += ".pdf"; + fileChooser.setSelectedFile(new File(name)); + } + + int retval = fileChooser.showSaveDialog(getEditor()); + + String fileName = null; + String type = null; + + if (retval == JFileChooser.APPROVE_OPTION) { + File f = SciNotes.fileToCanonicalFile(fileChooser.getSelectedFile()); + initialDirectoryPath = f.getPath(); + if (f.exists()) { + if (ScilabModalDialog.show(getEditor(), SciNotesMessages.REPLACE_FILE_TITLE, + SciNotesMessages.FILE_ALREADY_EXIST, IconType.QUESTION_ICON, + ButtonType.YES_NO) == AnswerOption.NO_OPTION) { + return; + } + } + + boolean hasNoExtension = true; + fileName = f.getName(); + if (fileName.lastIndexOf(DOT) != -1) { + int len = fileName.substring(fileName.lastIndexOf(DOT), fileName.length()).length(); + if (len >= 2 && len <= 4) { + hasNoExtension = false; + extension = fileName.substring(fileName.lastIndexOf(DOT) + 1, fileName.length()); + } + } + + if (extension == null) { + if (fileChooser.getFileFilter() == pdfFilter) { + extension = "pdf"; + type = CodeExporter.PDF; + } else if (fileChooser.getFileFilter() == psFilter) { + extension = "ps"; + type = CodeExporter.PS; + } else if (fileChooser.getFileFilter() == epsFilter) { + extension = "eps"; + type = CodeExporter.EPS; + } else if (fileChooser.getFileFilter() == rtfFilter) { + extension = "rtf"; + type = CodeExporter.RTF; + } else { + extension = ""; + type = null; + } + } else { + if (extension.equalsIgnoreCase("pdf")) { + type = CodeExporter.PDF; + } else if (extension.equalsIgnoreCase("ps")) { + type = CodeExporter.PS; + } else if (extension.equalsIgnoreCase("eps")) { + type = CodeExporter.EPS; + } else if (extension.equalsIgnoreCase("rtf")) { + type = CodeExporter.RTF; + } + } + + if (hasNoExtension) { + fileName = f.getPath() + DOT + extension; + } else { + fileName = f.getPath(); + } + } else if (retval == JFileChooser.CANCEL_OPTION) { + fileName = null; + } + + if (!codeConverterLoaded) { + LoadClassPath.loadOnUse("copyAsHTMLinScinotes"); + LoadClassPath.loadOnUse("pdf_ps_eps_graphic_export"); + codeConverterLoaded = true; + } + + if (fileName != null && type != null) { + getEditor().getTextPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + CodeExporter.convert(getEditor().getTextPane(), fileName, type, PageSetupAction.getPageFormat()); + getEditor().getTextPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + } + + /** + * Create the MenuItem for print action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new ExportAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindAction.java new file mode 100755 index 000000000..4a877629d --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindAction.java @@ -0,0 +1,1320 @@ +/* Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Sylvestre KOUMAR + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2009 - DIGITEO - Antoine ELIAS + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Color; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.awt.event.WindowListener; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.Highlighter; + +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.bridge.textbox.SwingScilabTextBox; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.SearchManager; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * FindAction + * @author Sylvestre KOUMAR + * @author Allan CORNET + * @author Antoine ELIAS + * @author Vincent COUVERT + * @author Calixte DENIZET + */ +public final class FindAction extends DefaultAction implements WindowFocusListener { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -5499974793656106222L; + + private static final int GAP = 5; + private static final int THREE = 3; + + private static final String FILTERNEWLINES = "filterNewlines"; + private static final String ESCAPE = "ESCAPE"; + + private static final Color SELECTEDCOLOR = new Color(205, 183, 158); + private static final Highlighter.HighlightPainter ACTIVEPAINTER = new DefaultHighlighter.DefaultHighlightPainter(Color.green); + private static final Highlighter.HighlightPainter INACTIVEPAINTER = new DefaultHighlighter.DefaultHighlightPainter(Color.yellow); + private static final Highlighter.HighlightPainter SELECTEDPAINTER = new DefaultHighlighter.DefaultHighlightPainter(SELECTEDCOLOR); + + private static String previousSearch; + + private static boolean windowAlreadyExist; + private static FindAction current; + + private JFrame frame; + private JButton buttonClose; + private JButton buttonFind; + private ButtonGroup buttonGroup1; + private ButtonGroup buttonGroup2; + private JButton buttonReplace; + private JButton buttonReplaceAll; + private JButton buttonReplaceFind; + private JCheckBox checkCase; + private JCheckBox checkRegular; + private JCheckBox checkCircular; + private JCheckBox checkWhole; + private JComboBox comboFind; + private JComboBox comboReplace; + private JLabel labelFind; + private JLabel labelReplace; + private JPanel panelButton; + private JPanel panelDirection; + private JPanel panelFind; + private JPanel panelFrame; + private JPanel panelOptions; + private JPanel panelScope; + private SwingScilabTextBox statusBar; + private JRadioButton radioAll; + private JRadioButton radioFromCaret; + private JRadioButton radioBackward; + private JRadioButton radioForward; + private JRadioButton radioSelection; + + private String oldWord; + private String newWord; + private String wordToFind; + + private String lastSearch = ""; + private String lastReplace = ""; + + private int startSelectedLines; + private int endSelectedLines; + + private int startFind; + private int endFind; + + private boolean restarted; + + private Object[] highlighters; + private Object selectedHighlight; + + private String previousRegexp; + private int previousIndex; + private List<Integer[]> foundOffsets; + private final MyListener myListener = new MyListener(); + + private boolean comboReplaceCanceled; + private boolean comboFindCanceled; + + private Document previousDocument; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public FindAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + if (windowAlreadyExist) { + if (current != this) { + current.closeFindReplaceWindow(); + current = this; + findReplaceBox(); + } else { + frame.setVisible(true); + buttonFind.requestFocus(); + frame.toFront(); + } + } else { + current = this; + findReplaceBox(); + } + + previousRegexp = ""; + previousIndex = -1; + getEditor().getTextPane().removeCaretListener(myListener); + startSelectedLines = 0; + endSelectedLines = 0; + + try { + // If some text is selected, it is used in find. + //if more than one line is selected set radio button "selected lines" at true + // else find and replace action is applied to the entire document + JEditorPane scinotesTextPane = getEditor().getTextPane(); + int startPos = scinotesTextPane.getSelectionStart(); + int endPos = scinotesTextPane.getSelectionEnd(); + Element root = scinotesTextPane.getDocument().getDefaultRootElement(); + int startLine = root.getElementIndex(startPos); + int endLine = root.getElementIndex(endPos); + + if (startPos != endPos) { + if (startLine != endLine) { + radioSelection.doClick(); + comboFind.setSelectedIndex(-1); + comboReplace.setSelectedIndex(-1); + } else { + radioAll.doClick(); + comboFind.getEditor().setItem(scinotesTextPane.getDocument().getText(startPos, endPos - startPos)); + comboFind.getEditor().selectAll(); + } + } else { + radioAll.doClick(); + comboFind.setSelectedIndex(-1); + comboReplace.setSelectedIndex(-1); + } + windowAlreadyExist = true; + updateFindReplaceButtonStatus(); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new FindAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new FindAction(tooltip, editor)); + } + + /** + * Close the eventually opened FindReplaceWindow + */ + public static void close() { + if (current != null) { + current.closeFindReplaceWindow(); + } + } + + /** + * {@inheritedDoc} + */ + @Override + public void windowGainedFocus(WindowEvent e) { + if (e.getWindow() == getEditor().getSwingParentWindow()) { + frame.setAlwaysOnTop(true); + } + } + + /** + * {@inheritedDoc} + */ + @Override + public void windowLostFocus(WindowEvent e) { + if (e.getOppositeWindow() != frame && e.getOppositeWindow() != getEditor().getSwingParentWindow()) { + frame.setAlwaysOnTop(false); + } + } + + /** + * findReplaceBox + */ + public void findReplaceBox() { + + //Find & Replace Frame + frame = new JFrame(); + frame.setAlwaysOnTop(true); + frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE , 0), ESCAPE); + frame.getRootPane().getActionMap().put(ESCAPE, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + closeFindReplaceWindow(); + } + }); + + frame.setIconImage(new ImageIcon(FindIconHelper.findIcon("scilab")).getImage()); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + frame.setTitle(SciNotesMessages.FIND_REPLACE); + frame.setResizable(false); + + getEditor().getSwingParentWindow().addWindowFocusListener(this); + frame.addWindowFocusListener(this); + + buttonGroup1 = new ButtonGroup(); + buttonGroup2 = new ButtonGroup(); + panelFrame = new JPanel(); + panelDirection = new JPanel(); + radioForward = new JRadioButton(); + radioBackward = new JRadioButton(); + panelScope = new JPanel(); + radioAll = new JRadioButton(); + radioFromCaret = new JRadioButton(); + radioSelection = new JRadioButton(); + panelOptions = new JPanel(); + checkCase = new JCheckBox(); + checkWhole = new JCheckBox(); + checkRegular = new JCheckBox(); + checkCircular = new JCheckBox(); + panelFind = new JPanel(); + labelFind = new JLabel(); + labelReplace = new JLabel(); + comboFind = new JComboBox(); + comboReplace = new JComboBox(); + panelButton = new JPanel(); + buttonFind = new JButton(); + buttonReplaceFind = new JButton(); + buttonReplace = new JButton(); + buttonReplaceAll = new JButton(); + buttonClose = new JButton(); + statusBar = new SwingScilabTextBox(); + + panelFrame.setLayout(new BoxLayout(panelFrame, BoxLayout.PAGE_AXIS)); + panelFrame.setBorder(BorderFactory.createEmptyBorder(2 * GAP, 2 * GAP, 2 * GAP, 2 * GAP)); + + /* Pattern to search and replace*/ + labelFind.setText(SciNotesMessages.FIND); + labelReplace.setText(SciNotesMessages.REPLACE); + + comboFind.setEditable(true); + comboReplace.setEditable(true); + + panelFind.setLayout(new GridLayout(2, 2, GAP, GAP)); + panelFind.add(labelFind); + panelFind.add(comboFind); + panelFind.add(labelReplace); + panelFind.add(comboReplace); + panelFrame.add(panelFind); + + /* Search direction selection*/ + panelDirection.setBorder(BorderFactory.createTitledBorder(SciNotesMessages.DIRECTION)); + + buttonGroup1.add(radioForward); + radioForward.setText(SciNotesMessages.FORWARD); + buttonGroup1.add(radioBackward); + radioBackward.setText(SciNotesMessages.BACKWARD); + + panelDirection.setLayout(new GridLayout(3, 1, GAP, GAP)); + panelDirection.add(radioForward); + panelDirection.add(radioBackward); + + /* Scope for search */ + panelScope.setBorder(BorderFactory.createTitledBorder(SciNotesMessages.SCOPE)); + + buttonGroup2.add(radioAll); + radioAll.setText(SciNotesMessages.SELECT_ALL); + + buttonGroup2.add(radioFromCaret); + radioFromCaret.setText(SciNotesMessages.SELECT_FROM_CARET); + + buttonGroup2.add(radioSelection); + radioSelection.setText(SciNotesMessages.SELECTED_LINES); + + panelScope.setLayout(new GridLayout(3, 1, GAP, GAP)); + panelScope.add(radioAll); + panelScope.add(radioFromCaret); + panelScope.add(radioSelection); + + JPanel panelDirectionScope = new JPanel(); + panelDirectionScope.setLayout(new GridLayout(1, 2, GAP, GAP)); + panelDirectionScope.add(panelDirection); + panelDirectionScope.add(panelScope); + panelFrame.add(panelDirectionScope); + + /* Misc Options */ + panelOptions.setBorder(BorderFactory.createTitledBorder(SciNotesMessages.OPTIONS)); + + checkCase.setText(SciNotesMessages.CASE_SENSITIVE); + checkWhole.setText(SciNotesMessages.WHOLE_WORD); + checkRegular.setText(SciNotesMessages.REGULAR_EXPRESSIONS); + checkCircular.setText(SciNotesMessages.CIRCULAR_SEARCH); + + checkCircular.setSelected(true); + panelOptions.setLayout(new GridLayout(2, 2, GAP, GAP)); + panelOptions.add(checkCase); + panelOptions.add(checkRegular); + panelOptions.add(checkWhole); + panelOptions.add(checkCircular); + panelFrame.add(panelOptions); + + buttonFind.setText(SciNotesMessages.FIND_BUTTON); + buttonReplaceFind.setText(SciNotesMessages.REPLACE_FIND); + buttonReplace.setText(SciNotesMessages.REPLACE); + buttonReplaceAll.setText(SciNotesMessages.REPLACE_ALL); + buttonClose.setText(SciNotesMessages.CLOSE); + statusBar.setText(""); + + panelButton.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); + panelButton.setLayout(new GridLayout(THREE, THREE, GAP, GAP)); + panelButton.add(new JLabel()); + panelButton.add(buttonFind); + panelButton.add(buttonReplaceFind); + panelButton.add(new JLabel()); + panelButton.add(buttonReplace); + panelButton.add(buttonReplaceAll); + panelButton.add(new JLabel()); + panelButton.add(new JLabel()); + panelButton.add(buttonClose); + + panelFrame.add(panelButton); + panelFrame.add(statusBar); + + frame.setContentPane(panelFrame); + + frame.pack(); + frame.setLocationRelativeTo(getEditor()); + frame.setVisible(true); + + buttonReplaceFind.setEnabled(false); + buttonReplace.setEnabled(false); + buttonFind.setEnabled(false); + buttonReplaceAll.setEnabled(false); + + radioForward.setSelected(true); + radioAll.doClick(); + + fillSearch(); + fillReplace(); + + restoreConfiguration(); + + ((JTextField) comboReplace.getEditor().getEditorComponent()).getDocument().putProperty(FILTERNEWLINES, Boolean.FALSE); + ((JTextField) comboFind.getEditor().getEditorComponent()).getDocument().putProperty(FILTERNEWLINES, Boolean.FALSE); + checkCase.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveCaseSensitive(checkCase.isSelected()); + updateFindReplaceButtonStatus(); + } + }); + + checkWhole.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveWholeWord(checkWhole.isSelected()); + updateFindReplaceButtonStatus(); + } + }); + + checkCircular.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveCircularSearch(checkCircular.isSelected()); + updateFindReplaceButtonStatus(); + } + }); + + checkRegular.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveRegularExpression(checkRegular.isSelected()); + updateFindReplaceButtonStatus(); + } + }); + + /*behaviour of buttons*/ + radioSelection.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + JEditorPane scinotesTextPane = getEditor().getTextPane(); + Element root = scinotesTextPane.getDocument().getDefaultRootElement(); + int startPos = scinotesTextPane.getSelectionStart(); + int endPos = scinotesTextPane.getSelectionEnd(); + int startLine = root.getElementIndex(startPos); + int endLine = root.getElementIndex(endPos); + startSelectedLines = root.getElement(startLine).getStartOffset(); + endSelectedLines = root.getElement(endLine).getEndOffset() - 1; + + scinotesTextPane.setCaretPosition(startSelectedLines); + + removeAllHighlights(); + setSelectedHighlight(); + + scinotesTextPane.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + JFrame opposite = (JFrame) SwingUtilities.getAncestorOfClass(JFrame.class, e.getOppositeComponent()); + if (opposite == frame) { + removeAllHighlights(); + previousRegexp = ""; + radioAll.setSelected(true); + getEditor().getTextPane().removeFocusListener(this); + } + } + + @Override + public void focusLost(FocusEvent e) { } + }); + + updateFindReplaceButtonStatus(); + } + }); + + radioAll.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + removeAllHighlights(); + previousRegexp = ""; + updateFindReplaceButtonStatus(); + } + }); + + radioFromCaret.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + removeAllHighlights(); + previousRegexp = ""; + updateFindReplaceButtonStatus(); + } + }); + + radioBackward.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateFindReplaceButtonStatus(); + } + }); + + buttonFind.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateRecentSearch(); + findText(); + } + }); + + buttonReplace.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateRecentSearch(); + updateRecentReplace(); + + JEditorPane scinotesTextPane = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) scinotesTextPane.getDocument(); + + doc.mergeEditsBegin(); + replaceOnlyText(); + doc.mergeEditsEnd(); + } + + }); + + buttonReplaceFind.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateRecentSearch(); + updateRecentReplace(); + + JEditorPane scinotesTextPane = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) scinotesTextPane.getDocument(); + + doc.mergeEditsBegin(); + if (buttonReplace.isEnabled()) { + replaceText(); + } + doc.mergeEditsEnd(); + findText(); + } + }); + + buttonReplaceAll.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateRecentSearch(); + updateRecentReplace(); + + JEditorPane scinotesTextPane = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) scinotesTextPane.getDocument(); + int start = 0; + int end = doc.getLength(); + String text = ""; + + boolean wholeWordSelected = checkWhole.isSelected() && checkWhole.isEnabled(); + boolean regexpSelected = checkRegular.isSelected(); + boolean caseSelected = checkCase.isSelected(); + + // save current caret position to restore it at the end + int currentCaretPos = scinotesTextPane.getCaretPosition(); + + if (radioSelection.isSelected()) { + start = startSelectedLines; + end = endSelectedLines; + try { + text = doc.getText(startSelectedLines, endSelectedLines - startSelectedLines); + } catch (BadLocationException ex) { } + } else if (radioFromCaret.isSelected()) { + if (radioForward.isSelected()) { + start = currentCaretPos; + end = doc.getLength(); + } else { + start = 0; + end = currentCaretPos; + } + try { + text = doc.getText(start, end - start); + } catch (BadLocationException ex) { } + } else { + text = doc.getText(); + } + + oldWord = (String) comboFind.getEditor().getItem(); + newWord = (String) comboReplace.getEditor().getItem(); + setPreviousSearch(oldWord); + + Pattern pattern = SearchManager.generatePattern(oldWord, caseSelected, wholeWordSelected, regexpSelected); + Matcher matcher = pattern.matcher(text); + String replacedText; + if (regexpSelected) { + newWord = newWord.replaceAll("\\\\r\\\\n|\\\\n", "\n").replaceAll("\\\\t", "\t"); + replacedText = matcher.replaceAll(newWord); + } else { + replacedText = matcher.replaceAll(Matcher.quoteReplacement(newWord)); + } + if (replacedText.compareTo(text) != 0 && text.length() > 0) { + // only touch document if any replacement took place + try { + List<ScilabDocument.Anchor> anchors = doc.getAnchorsBetween(start, end); + doc.mergeEditsBegin(); + doc.setFocused(true); + doc.replace(start, text.length(), replacedText, null); + doc.mergeEditsEnd(); + Element root = doc.getDefaultRootElement(); + for (ScilabDocument.Anchor anchor : anchors) { + ScilabDocument.ScilabLeafElement line = (ScilabDocument.ScilabLeafElement) root.getElement(anchor.getLine()); + line.setAnchor(anchor.toString()); + } + if (getEditor().getNavigator() != null) { + getEditor().getNavigator().update(); + } + previousRegexp = ""; + previousIndex = -1; + buttonReplace.setEnabled(false); + buttonReplaceFind.setEnabled(false); + buttonReplaceAll.setEnabled(false); + scinotesTextPane.setCaretPosition(Math.min(currentCaretPos, doc.getLength())); + } catch (BadLocationException e1) { + e1.printStackTrace(); + } + } + if (radioSelection.isSelected()) { + removeAllHighlights(); + endSelectedLines = startSelectedLines + replacedText.length(); + setSelectedHighlight(); + } + } + }); + + buttonClose.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + closeFindReplaceWindow(); + } + }); + + comboReplace.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + comboReplaceCanceled = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } + }); + + comboReplace.getEditor().getEditorComponent().addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent e) { } + @Override + public void mousePressed(MouseEvent e) { + closeComboPopUp(); + updateFindReplaceButtonStatus(); + } + @Override + public void mouseExited(MouseEvent e) { } + @Override + public void mouseEntered(MouseEvent e) { } + @Override + public void mouseClicked(MouseEvent e) { } + }); + + comboReplace.getEditor().getEditorComponent().addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { } + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + if (comboReplaceCanceled) { + comboReplaceCanceled = false; + } else { + closeFindReplaceWindow(); + } + } + + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + replaceText(); + findText(); + buttonReplaceFind.requestFocus(); + } + + updateFindReplaceButtonStatus(); + } + @Override + public void keyPressed(KeyEvent e) { } + }); + + comboFind.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + comboFindCanceled = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } + }); + + comboFind.getEditor().getEditorComponent().addMouseListener(new MouseListener() { + @Override + public void mouseReleased(MouseEvent arg0) { } + @Override + public void mousePressed(MouseEvent arg0) { + closeComboPopUp(); + } + @Override + public void mouseExited(MouseEvent arg0) { } + @Override + public void mouseEntered(MouseEvent arg0) { } + @Override + public void mouseClicked(MouseEvent arg0) { } + }); + + comboFind.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updateFindReplaceButtonStatus(); + } + }); + + comboFind.getEditor().getEditorComponent().addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { } + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + if (comboFindCanceled) { + comboFindCanceled = false; + } else { + closeFindReplaceWindow(); + } + } + + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + buttonFind.requestFocus(); + findText(); + } + + updateFindReplaceButtonStatus(); + } + + @Override + public void keyPressed(KeyEvent e) { } + }); + + frame.addWindowListener(new WindowListener() { + @Override + public void windowClosed(WindowEvent e) { } + @Override + public void windowDeiconified(WindowEvent e) { } + @Override + public void windowActivated(WindowEvent e) { } + + @Override + public void windowClosing(WindowEvent e) { + closeFindReplaceWindow(); + } + + @Override + public void windowDeactivated(WindowEvent e) { } + @Override + public void windowIconified(WindowEvent e) { } + @Override + public void windowOpened(WindowEvent e) { } + }); + } + + /** + * Close combo pop-up + */ + private void closeComboPopUp() { + if (comboFind.isPopupVisible()) { + comboFind.hidePopup(); + } + + if (comboReplace.isPopupVisible()) { + comboReplace.hidePopup(); + } + } + + /** + * fill comboFind + */ + private void fillSearch() { + comboFind.removeAllItems(); + List<String> recentFind = ConfigSciNotesManager.getRecentSearch(); + for (String item : recentFind) { + comboFind.addItem(item); + } + } + + /** + * fill comboReplace + */ + private void fillReplace() { + comboReplace.removeAllItems(); + List<String> recentReplace = ConfigSciNotesManager.getRecentReplace(); + for (String item : recentReplace) { + comboReplace.addItem(item); + } + } + + /** + * Update recent search + */ + private void updateRecentSearch() { + String word = (String) comboFind.getEditor().getItem(); + if (word != null && word.length() != 0 && !word.equals(lastSearch)) { + List<String> recentFind = ConfigSciNotesManager.getRecentSearch(); + if (!recentFind.contains(word)) { + comboFind.addItem(word); + ConfigSciNotesManager.saveRecentSearch(word); + lastSearch = word; + } + } + } + + /** + * Update recent replace + */ + private void updateRecentReplace() { + String word = (String) comboReplace.getEditor().getItem(); + if (word != null && word.length() != 0 && !word.equals(lastReplace)) { + List<String> recentReplace = ConfigSciNotesManager.getRecentReplace(); + if (!recentReplace.contains(word)) { + comboReplace.addItem(word); + ConfigSciNotesManager.saveRecentReplace(word); + lastReplace = word; + } + } + } + + /** + * Restore configuration + */ + private void restoreConfiguration() { + checkRegular.setSelected(ConfigSciNotesManager.getRegularExpression()); + checkCircular.setSelected(ConfigSciNotesManager.getCircularSearch()); + checkWhole.setSelected(ConfigSciNotesManager.getWholeWord()); + checkCase.setSelected(ConfigSciNotesManager.getCaseSensitive()); + } + + /** + * Update status of buttons + */ + protected void updateFindReplaceButtonStatus() { + String textFind = (String) comboFind.getEditor().getItem(); + if (textFind.compareTo("") != 0) { + buttonFind.setEnabled(true); + buttonReplace.setEnabled(true); + buttonReplaceAll.setEnabled(true); + buttonReplaceFind.setEnabled(true); + statusBar.setText(""); + } else { + buttonFind.setEnabled(false); + buttonReplace.setEnabled(false); + buttonReplaceAll.setEnabled(false); + buttonReplaceFind.setEnabled(false); + } + + // permit to choose "whole word" only if the input is a single word + Pattern patternWholeWord = Pattern.compile("\\w*"); + Matcher matcherWholeWord = patternWholeWord.matcher(textFind); + + checkWhole.setEnabled(false); + + if (matcherWholeWord.find()) { + if ((matcherWholeWord.end() - matcherWholeWord.start()) == textFind.length()) { + checkWhole.setEnabled(true); + } + } + + // if we search a regexp, we first need to know if the regexp is valid or not + if (checkRegular.isSelected()) { + try { + Pattern.compile(textFind); + } catch (PatternSyntaxException pse) { + statusBar.setText(String.format(SciNotesMessages.INVALID_REGEXP, textFind)); + buttonFind.setEnabled(false); + buttonReplaceAll.setEnabled(false); + } + } + + if (buttonReplace.isEnabled() && oldWord != null && oldWord.compareTo(textFind) != 0) { + buttonReplace.setEnabled(false); + buttonReplaceFind.setEnabled(false); + } + } + + /** + * Add highlights on the view to see the searched word + * @param active to highlight an active word + */ + public void addHighlighters(boolean active) { + Highlighter hl = getEditor().getTextPane().getHighlighter(); + removeAllHighlights(); + highlighters = new Object[foundOffsets.size()]; + for (int i = 0; i < foundOffsets.size(); i++) { + try { + if (active) { + highlighters[i] = hl.addHighlight(foundOffsets.get(i)[0], foundOffsets.get(i)[1], ACTIVEPAINTER); + } else { + highlighters[i] = hl.addHighlight(foundOffsets.get(i)[0], foundOffsets.get(i)[1], INACTIVEPAINTER); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + if (radioSelection.isSelected()) { + setSelectedHighlight(); + } + } + + /** + * Change the highlight with index n to active (or not) the word + * @param n the index + * @param active to highlight an active word + */ + public void changeHighlighter(int n, boolean active) { + if (highlighters != null) { + Highlighter hl = getEditor().getTextPane().getHighlighter(); + hl.removeHighlight(highlighters[n]); + try { + if (active) { + highlighters[n] = hl.addHighlight(foundOffsets.get(n)[0], foundOffsets.get(n)[1], ACTIVEPAINTER); + } else { + highlighters[n] = hl.addHighlight(foundOffsets.get(n)[0], foundOffsets.get(n)[1], INACTIVEPAINTER); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + if (radioSelection.isSelected()) { + setSelectedHighlight(); + } + } + } + + /** + * Set the selection where to search + */ + public void setSelectedHighlight() { + Highlighter hl = getEditor().getTextPane().getHighlighter(); + try { + if (selectedHighlight != null) { + hl.removeHighlight(selectedHighlight); + } + selectedHighlight = hl.addHighlight(startSelectedLines, endSelectedLines, SELECTEDPAINTER); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Remove an highlight + * @param n th index of the word + **/ + public void removeHighlighter(int n) { + if (highlighters != null) { + Highlighter hl = getEditor().getTextPane().getHighlighter(); + hl.removeHighlight(highlighters[n]); + } + } + + /** + * Remove all Highlights + */ + public void removeAllHighlights() { + Highlighter hl = getEditor().getTextPane().getHighlighter(); + if (highlighters != null) { + for (int i = 0; i < highlighters.length; i++) { + hl.removeHighlight(highlighters[i]); + } + } + if (selectedHighlight != null) { + hl.removeHighlight(selectedHighlight); + selectedHighlight = null; + } + } + + /** + * Get the next keyword after the position pos + * @param pos the position of the caret + * @param forward for a forward search + * @param circular for a circular search + * @return the index of the word + */ + private int getSearched(int pos, boolean forward, boolean circular) { + int index = -1; + for (int i = 0; i < foundOffsets.size(); i++) { + if (forward && foundOffsets.get(i)[0] >= pos) { + index = i; + break; + } else if (!forward && foundOffsets.get(i)[0] >= pos) { + if (i == 0) { + return -1; + } + index = i - 1; + break; + } + } + + if (index == -1 && circular) { + if (forward) { + return 0; + } else { + return foundOffsets.size() - 1; + } + } + + return index; + } + + /** + * Generate the offsets of the searched word + * @return a boolean if a job has been done + */ + public boolean generateOffsets() { + boolean caseSensitive = checkCase.isSelected(); + boolean wholeWord = checkWhole.isSelected() && checkWhole.isEnabled(); + boolean useRegexp = checkRegular.isSelected(); + boolean onlySelectedLines = radioSelection.isSelected(); + Document doc = getEditor().getTextPane().getDocument(); + wordToFind = (String) comboFind.getEditor().getItem(); + + String strregexp = SearchManager.generatePattern(wordToFind, caseSensitive, wholeWord, useRegexp).toString(); + if (doc != previousDocument || !previousRegexp.equals(strregexp)) { + previousRegexp = strregexp; + if (doc != previousDocument) { + previousDocument = doc; + } + if (onlySelectedLines) { + foundOffsets = SearchManager.findWord(doc, wordToFind, startSelectedLines, endSelectedLines, caseSensitive, wholeWord, useRegexp); + } else { + foundOffsets = SearchManager.findWord(doc, wordToFind, 0, doc.getLength(), caseSensitive, wholeWord, useRegexp); + } + return true; + } + return false; + } + + /** + * findText + */ + private void findText() { + boolean circularSearchSelected = checkCircular.isSelected(); + boolean forwardSearch = radioForward.isSelected(); + boolean backwardSearch = radioBackward.isSelected(); + + String exp = (String) comboFind.getEditor().getItem(); + if (exp.compareTo("") == 0) { + return; + } + + setPreviousSearch(wordToFind); + + JEditorPane scinotesTextPane = getEditor().getTextPane(); + + if (generateOffsets()) { + addHighlighters(false); + previousIndex = -1; + } + + int currentCaretPos = scinotesTextPane.getSelectionStart(); + + if (forwardSearch) { + currentCaretPos = scinotesTextPane.getSelectionEnd(); + } else { + currentCaretPos = scinotesTextPane.getSelectionStart() - 1; + } + + statusBar.setText(""); + + int size = foundOffsets.size(); + if (size > 0) { + int nextIndex = -1; + if (previousIndex == -1) { + nextIndex = getSearched(currentCaretPos, !backwardSearch, circularSearchSelected); + } else { + if (backwardSearch) { + if (circularSearchSelected) { + nextIndex = (size + previousIndex - 1) % size; + } else { + nextIndex = previousIndex - 1; + } + } else { + if (circularSearchSelected) { + nextIndex = (previousIndex + 1) % size; + } else { + nextIndex = previousIndex + 1; + } + } + changeHighlighter(previousIndex, false); + } + + if (nextIndex == size) { + nextIndex = -1; + } + + if (nextIndex != -1) { + if (restarted) { + statusBar.setText(""); + restarted = false; + } else if (circularSearchSelected && size >= 2 && nextIndex <= previousIndex) { + statusBar.setText(SciNotesMessages.RESTART_FROM_BEGINNING); + restarted = true; + } + + changeHighlighter(nextIndex, true); + previousIndex = nextIndex; + if (backwardSearch) { + scinotesTextPane.setCaretPosition(foundOffsets.get(nextIndex)[0]); + } else { + scinotesTextPane.setCaretPosition(foundOffsets.get(nextIndex)[1]); + } + + scinotesTextPane.addFocusListener(myListener); + buttonReplace.setEnabled(true); + buttonReplaceFind.setEnabled(true); + + startFind = foundOffsets.get(nextIndex)[0]; + endFind = foundOffsets.get(nextIndex)[1]; + } else { + startFind = 0; + endFind = 0; + buttonFind.setEnabled(false); + buttonReplace.setEnabled(false); + buttonReplaceFind.setEnabled(false); + statusBar.setText(String.format(SciNotesMessages.STRING_NOT_FOUND, wordToFind)); + } + } else { // nothing has been found + statusBar.setText(String.format(SciNotesMessages.STRING_NOT_FOUND, wordToFind)); + buttonFind.setEnabled(false); + buttonReplace.setEnabled(false); + buttonReplaceFind.setEnabled(false); + buttonReplaceAll.setEnabled(false); + } + } + + /** + * replaceOnlyText + */ + private void replaceOnlyText() { + replaceText(); + buttonReplace.setEnabled(false); + buttonReplaceFind.setEnabled(false); + } + + /** + * replaceText + */ + private void replaceText() { + boolean caseSensitive = checkCase.isSelected(); + boolean wholeWord = checkWhole.isSelected() && checkWhole.isEnabled(); + boolean useRegexp = checkRegular.isSelected(); + + String find = (String) comboFind.getEditor().getItem(); + String replace = (String) comboReplace.getEditor().getItem(); + if (useRegexp) { + replace = replace.replaceAll("\\\\r\\\\n|\\\\n", "\n").replaceAll("\\\\t", "\t"); + } else { + replace = Matcher.quoteReplacement(replace); + } + + if (find.compareTo("") == 0 || (startFind == endFind)) { + return; + } + + setPreviousSearch(find); + + JEditorPane scinotesTextPane = getEditor().getTextPane(); + + /* + * we replace only the current result and then disable replace and replace find button + * same behaviour as find and replace in eclipse + */ + + try { + Pattern pattern = SearchManager.generatePattern(find, caseSensitive, wholeWord, useRegexp); + Matcher matcher = pattern.matcher(scinotesTextPane.getText(startFind, endFind - startFind + 1)); + String replacedText = matcher.replaceAll(replace); + ScilabDocument doc = (ScilabDocument) scinotesTextPane.getDocument(); + doc.setFocused(true); + doc.replace(startFind, endFind - startFind + 1, replacedText, null); + scinotesTextPane.setCaretPosition(startFind + replacedText.length()); + endSelectedLines += replacedText.length() - (endFind - startFind + 1); + previousRegexp = ""; + previousIndex = -1; + if (generateOffsets()) { + addHighlighters(false); + } + } catch (BadLocationException ex) { + ex.printStackTrace(); + } + } + + /** + * closeFindReplaceWindow + */ + public void closeFindReplaceWindow() { + if (windowAlreadyExist) { + JEditorPane scinotesTextPane = getEditor().getTextPane(); + if (scinotesTextPane != null) { + scinotesTextPane.getHighlighter().removeAllHighlights(); + int start = scinotesTextPane.getSelectionStart(); + int end = scinotesTextPane.getSelectionEnd(); + scinotesTextPane.select(start, end); + } + getEditor().getSwingParentWindow().removeWindowFocusListener(this); + frame.removeWindowFocusListener(this); + frame.dispose(); + windowAlreadyExist = false; + } + } + + /** + * Get the previous search + * @return the previuos search + */ + public static String getPreviousSearch() { + return previousSearch; + } + + /** + * Set the previous search + * @param previousSearch String + */ + public static void setPreviousSearch(String previousSearch) { + FindAction.previousSearch = previousSearch; + } + + /** + * Inner class to handle events (used as a singleton) + */ + private class MyListener implements CaretListener, FocusListener { + + /** + * Constructor + */ + public MyListener() { + super(); + } + + /** + * focusGained in interface FocusListener + * @param e FocusEvent + */ + @Override + public void focusGained(FocusEvent e) { + if (previousIndex != -1) { + int start = foundOffsets.get(previousIndex)[0]; + int end = foundOffsets.get(previousIndex)[1]; + getEditor().getTextPane().select(start, end); + } + getEditor().getTextPane().addCaretListener(this); + } + + /** + * focusLost in interface FocusListener + * @param e FocusEvent + */ + @Override + public void focusLost(FocusEvent e) { } + + /** + * caretUpdate in interface CaretListener + * @param e FocusEvent + */ + @Override + public void caretUpdate(CaretEvent e) { + removeAllHighlights(); + getEditor().getTextPane().removeCaretListener(this); + getEditor().getTextPane().removeFocusListener(this); + previousRegexp = ""; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindNextAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindNextAction.java new file mode 100755 index 000000000..0dfc8cdff --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindNextAction.java @@ -0,0 +1,102 @@ +/* Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Antoine ELIAS + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.util.List; + +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.SearchManager; + +/** + * + * @author Antoine ELIAS + * + */ +public final class FindNextAction extends DefaultAction { + + private static final long serialVersionUID = -9017015781643180532L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public FindNextAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * DoAction + */ + public void doAction() { + try { + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + int startPos = getEditor().getTextPane().getSelectionStart(); + int endPos = getEditor().getTextPane().getSelectionEnd(); + int startLine = doc.getDefaultRootElement().getElementIndex(startPos); + int endLine = doc.getDefaultRootElement().getElementIndex(endPos); + + //don't manage multiple lines quick find + if (startLine != endLine) { + return; + } + + String exp = null; + if (startPos == endPos) { + //nothing to search + if (FindAction.getPreviousSearch() == null) { + return; + } else { + exp = FindAction.getPreviousSearch(); + } + } else { + exp = doc.getText(startPos, endPos - startPos); + } + + //search from current position to end document + List<Integer[]> offsets = SearchManager.findWord(doc, exp, 0, doc.getLength(), true, false, false); + if (offsets.size() != 0) { + int index = -1; + for (int i = 0; i < offsets.size(); i++) { + if (offsets.get(i)[0] >= endPos + 1) { + index = i; + break; + } + } + + if (index == -1) { + index = 0; + } + + getEditor().getTextPane().select(offsets.get(index)[0], offsets.get(index)[1]); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new FindNextAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindPreviousAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindPreviousAction.java new file mode 100755 index 000000000..fe4514868 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/FindPreviousAction.java @@ -0,0 +1,102 @@ +/* Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Antoine ELIAS + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.util.List; + +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.SearchManager; + +/** + * + * @author Antoine ELIAS + * + */ +public final class FindPreviousAction extends DefaultAction { + + private static final long serialVersionUID = -9017015781643180532L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public FindPreviousAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * DoAction + */ + public void doAction() { + try { + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + int startPos = getEditor().getTextPane().getSelectionStart(); + int endPos = getEditor().getTextPane().getSelectionEnd(); + int startLine = doc.getDefaultRootElement().getElementIndex(startPos); + int endLine = doc.getDefaultRootElement().getElementIndex(endPos); + + //don't manage multiple lines quick find + if (startLine != endLine) { + return; + } + + String exp = null; + if (startPos == endPos) { + //nothing to search + if (FindAction.getPreviousSearch() == null) { + return; + } else { + exp = FindAction.getPreviousSearch(); + } + } else { + exp = doc.getText(startPos, endPos - startPos); + } + + //search from current position to end document + List<Integer[]> offsets = SearchManager.findWord(doc, exp, 0, doc.getLength(), true, false, false); + if (offsets.size() != 0) { + int index = -1; + for (int i = 0; i < offsets.size(); i++) { + if (offsets.get(i)[0] >= startPos) { + index = i - 1; + break; + } + } + + if (index == -1) { + index = offsets.size() - 1; + } + + getEditor().getTextPane().select(offsets.get(index)[0], offsets.get(index)[1]); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new FindPreviousAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GeneralSettingsAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GeneralSettingsAction.java new file mode 100755 index 000000000..97f966f51 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GeneralSettingsAction.java @@ -0,0 +1,66 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.commons.ScilabGeneralPrefs; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * SetFontAction Class + * @author Calixte DENIZET + */ +public class GeneralSettingsAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public GeneralSettingsAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + ScilabGeneralPrefs.openPreferences("scinotes/"); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new GeneralSettingsAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new GeneralSettingsAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GenerateHelpFromFunctionAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GenerateHelpFromFunctionAction.java new file mode 100755 index 000000000..591be1601 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GenerateHelpFromFunctionAction.java @@ -0,0 +1,138 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; + +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.text.Element; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.FunctionScanner; + +/** + * Generate help from a function definition + * @author Calixte DENIZET + */ +public class GenerateHelpFromFunctionAction extends DefaultAction { + + private static final long serialVersionUID = 5008914832562621484L; + + /** + * The help template + */ + public static final String TEMPLATE = "//\n" + + "//\n" + + "// Calling Sequence\n" + + "// [returnValues] = functionName(argsValues) // \n" + + "// Parameters\n" + + "// argsValuesOnColumn\n" + + "// returnValuesOnColumn\n" + + "// \n" + + "// Description\n" + + "// \n" + + "// \n" + + "// Examples\n" + + "// \n" + + "// \n" + + "// See Also\n" + + "// \n" + + "// \n" + + "// Authors\n" + + "// \n" + + "\n"; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public GenerateHelpFromFunctionAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int pos = sep.getCaretPosition(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + Element root = doc.getDefaultRootElement(); + Element e = root.getElement(root.getElementIndex(pos)); + if (e instanceof ScilabDocument.ScilabLeafElement) { + ScilabDocument.ScilabLeafElement se = (ScilabDocument.ScilabLeafElement) e; + if (se.isFunction()) { + FunctionScanner.FunctionInfo info = se.getFunctionInfo(); + String help = TEMPLATE.replaceFirst("functionName", info.functionName); + help = help.replaceFirst("returnValues", generateList(info.returnValues, ", ", "")); + help = help.replaceFirst("argsValues", generateList(info.argsValues, ", ", "")); + help = help.replaceFirst("returnValuesOnColumn", generateList(info.returnValues, ": \n// ", ": ")); + help = help.replaceFirst("argsValuesOnColumn", generateList(info.argsValues, ": \n// ", ": ")); + try { + doc.mergeEditsEnd(); + doc.insertString(e.getEndOffset(), help, null); + } catch (BadLocationException exc) { } + } + } + } + + /** + * Generate a string containing the list gave as argument in using sep as separator + * @param list the list + * @param sep the separator + * @param end a String to close + * @return the generated String + */ + private String generateList(List<String> list, String sep, String end) { + String str = ""; + for (int i = 0; i < list.size() - 1; i++) { + str += list.get(i) + sep; + } + if (list.size() >= 1) { + str += list.get(list.size() - 1) + end; + } + + return str; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + final MenuItem menuitem = createMenu(label, null, new GenerateHelpFromFunctionAction(label, editor), key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + Element root = editor.getTextPane().getDocument().getDefaultRootElement(); + int pos = editor.getTextPane().getCaretPosition(); + ScilabDocument.ScilabLeafElement elem = (ScilabDocument.ScilabLeafElement) root.getElement(root.getElementIndex(pos)); + menuitem.setEnabled(elem.isFunction()); + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GotoNextAnchorAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GotoNextAnchorAction.java new file mode 100755 index 000000000..1a32d4539 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GotoNextAnchorAction.java @@ -0,0 +1,61 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * GotoNextAnchorAction Class + * @author Calixte DENIZET + */ +public class GotoNextAnchorAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public GotoNextAnchorAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(sep.getCaretPosition()); + sep.scrollTextToLineNumber(doc.nextAnchorFrom(line) + 1, false); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new GotoNextAnchorAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GotoPreviousAnchorAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GotoPreviousAnchorAction.java new file mode 100755 index 000000000..4c08a2686 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/GotoPreviousAnchorAction.java @@ -0,0 +1,61 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * GotoPreviousAnchorAction Class + * @author Calixte DENIZET + */ +public class GotoPreviousAnchorAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public GotoPreviousAnchorAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(sep.getCaretPosition()); + sep.scrollTextToLineNumber(doc.previousAnchorFrom(line) + 1, false); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new GotoPreviousAnchorAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpAction.java new file mode 100755 index 000000000..0e3edff06 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpAction.java @@ -0,0 +1,71 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.action_binding.InterpreterManagement; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * HelpAction Class + * @author Bruno JOFRET + * + */ +public final class HelpAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -3024180292998640447L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public HelpAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + InterpreterManagement.requestScilabExec("help('scinotes')"); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new HelpAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new HelpAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpOnKeywordAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpOnKeywordAction.java new file mode 100755 index 000000000..74e87ba16 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpOnKeywordAction.java @@ -0,0 +1,116 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.StringTokenizer; + +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.action_binding.InterpreterManagement; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * HelpOnKeywordAction Class + * @author Calixte DENIZET + */ +public class HelpOnKeywordAction extends DefaultAction { + + private static final long serialVersionUID = -7241378949942315933L; + + protected boolean isPopup; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public HelpOnKeywordAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + String selection = ""; + int start = getEditor().getTextPane().getSelectionStart(); + int end = getEditor().getTextPane().getSelectionEnd(); + try { + if (start == end) { + String kw = getEditor().getTextPane().getHelpableKeyword(!isPopup); + if (kw != null) { + selection = kw; + } + } else { + selection = getEditor().getTextPane().getDocument().getText(start, end - start); + } + } catch (BadLocationException e) { } + + InterpreterManagement.requestScilabExec("help('" + selection + "')"); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + StringTokenizer token = new StringTokenizer(label, ";\uff1b"); + final String label1 = token.nextToken(); + final String label2 = token.nextToken(); + return createMenu(label1, label2, editor, key, new HelpOnKeywordAction(label1 + SciNotesMessages.DOTS, editor)); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @param hoka the HelpOnKeyword action + * @return MenuItem + */ + protected static MenuItem createMenu(final String label1, final String label2, final SciNotes editor, KeyStroke key, final HelpOnKeywordAction hoka) { + final MenuItem menuitem = createMenu(label1, null, hoka, key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + String select = editor.getTextPane().getSelectedText(); + if (select == null) { + String kw = editor.getTextPane().getHelpableKeyword(!hoka.isPopup); + if (kw != null) { + menuitem.setText(label1 + SciNotesMessages.QUOTE + kw + SciNotesMessages.QUOTE); + menuitem.setEnabled(true); + } else { + menuitem.setText(label1 + SciNotesMessages.DOTS); + menuitem.setEnabled(false); + } + } else { + menuitem.setText(label2); + menuitem.setEnabled(true); + } + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpOnKeywordInPopupAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpOnKeywordInPopupAction.java new file mode 100755 index 000000000..da009387c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/HelpOnKeywordInPopupAction.java @@ -0,0 +1,54 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.util.StringTokenizer; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * HelpOnKeywordAction Class + * @author Calixte DENIZET + */ +public class HelpOnKeywordInPopupAction extends HelpOnKeywordAction { + + private static final long serialVersionUID = -7189187227299495917L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public HelpOnKeywordInPopupAction(String name, SciNotes editor) { + super(name, editor); + isPopup = true; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + StringTokenizer token = new StringTokenizer(label, ";\uff1b"); + final String label1 = token.nextToken(); + final String label2 = token.nextToken(); + return createMenu(label1, label2, editor, key, new HelpOnKeywordInPopupAction(label1 + SciNotesMessages.DOTS, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/IncrementalSearchAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/IncrementalSearchAction.java new file mode 100755 index 000000000..f6200bc73 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/IncrementalSearchAction.java @@ -0,0 +1,392 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010-2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.KeyboardFocusManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.AbstractAction; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.KeyStroke; + +import org.scilab.modules.commons.ScilabConstants; +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * IncrementalSearchAction Class + * @author Calixte DENIZET + */ +public final class IncrementalSearchAction extends DefaultAction { + + private static final long serialVersionUID = -3093932085002970876L; + private static final String SCI = ScilabConstants.SCI.getPath(); + private static final String TAB = "tab"; + private static final ImageIcon CLOSEICON = new ImageIcon(SCI + "/modules/gui/images/icons/close-tab.png"); + private static final ImageIcon TOPICON = new ImageIcon(FindIconHelper.findIcon("go-top")); + private static final ImageIcon BOTICON = new ImageIcon(FindIconHelper.findIcon("go-bottom")); + private static final int BUTTONSIZE = 28; + + private static Map<SciNotes, SearchField> fields = new HashMap<SciNotes, SearchField>(); + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public IncrementalSearchAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + if (!fields.containsKey(getEditor())) { + SearchField field = new SearchField(); + fields.put(getEditor(), field); + getEditor().insertBottomComponent(field); + field.requestFocus(); + } else { + fields.get(getEditor()).requestFocus(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new IncrementalSearchAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new IncrementalSearchAction(tooltip, editor)); + } + + /** + * @param editor the editor where to close the search bar + */ + public static void close(SciNotes editor) { + if (fields.containsKey(editor)) { + fields.get(editor).removeListeners(); + fields.remove(editor); + } + } + + /** + * @param editor the editor where to close the search bar + * @return the word which is currently searching + */ + public static String getWord(SciNotes editor) { + if (fields.containsKey(editor)) { + return fields.get(editor).getWord(); + } + + return null; + } + + /** + * @param editor the editor where to close the search bar + * @return true if it is an exact search + */ + public static boolean getExact(SciNotes editor) { + if (fields.containsKey(editor)) { + return fields.get(editor).getExact(); + } + + return false; + } + + /** + * Inner class to have an incremental search field. + */ + @SuppressWarnings(value = { "serial" }) + class SearchField extends JPanel implements FocusListener, KeyListener { + + private String text; + private final JTextField field; + private boolean exact; + + /** + * Default Constructor + */ + public SearchField() { + super(new BorderLayout()); + field = new JTextField(); + field.addKeyListener(this); + field.addFocusListener(this); + field.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); + field.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), TAB); + field.getActionMap().put(TAB, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + getEditor().getTextPane().requestFocus(); + } + }); + JPanel panelButtons = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0)); + panelButtons.add(new CloseButton()); + panelButtons.add(new TopBotButtons(true)); + panelButtons.add(new TopBotButtons(false)); + JCheckBox check = new JCheckBox(SciNotesMessages.EXACT); + check.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + exact = e.getStateChange() == ItemEvent.SELECTED; + changeText(); + } + }); + panelButtons.add(check); + add(panelButtons, BorderLayout.WEST); + add(field, BorderLayout.CENTER); + setVisible(true); + } + + /** + * @return the word which is currently searching + */ + public String getWord() { + return field.getText(); + } + + /** + * @return true if it is an exact search + */ + public boolean getExact() { + return exact; + } + + /** + * {@inheritDoc} + */ + @Override + public void requestFocus() { + field.requestFocus(); + } + + /** + * {@inheritDoc} + */ + @Override + public void focusGained(FocusEvent e) { + if (text == null) { + changeText(); + } + field.select(0, field.getText().length()); + } + + /** + * {@inheritDoc} + */ + @Override + public void focusLost(FocusEvent e) { + text = null; + } + + /** + * Remove listeners + */ + public void removeListeners() { + field.removeFocusListener(field.getFocusListeners()[0]); + field.removeKeyListener(field.getKeyListeners()[0]); + } + + /** + * Hide the search field + */ + public void hideField() { + removeListeners(); + fields.remove(getEditor()); + getEditor().insertBottomComponent(null); + } + + /** + * {@inheritDoc} + */ + @Override + public void keyReleased(KeyEvent e) { + int key = e.getKeyCode(); + if (key == KeyEvent.VK_ESCAPE) { + hideField(); + return; + } + + if (key != KeyEvent.VK_LEFT && key != KeyEvent.VK_RIGHT && key != KeyEvent.VK_UP && key != KeyEvent.VK_DOWN) { + ScilabEditorPane sep = getEditor().getTextPane(); + int pos = sep.getSelectionStart(); + int start; + String str = field.getText(); + if (str != null) { + sep.highlightWords(str, exact); + if (!exact) { + str = str.toLowerCase(); + } + if (key == KeyEvent.VK_ENTER && ((e.getModifiers() & KeyEvent.SHIFT_MASK) != 0)) { + start = text.lastIndexOf(str, pos - 1); + e.consume(); + } else { + if (key == KeyEvent.VK_ENTER) { + pos++; + } + start = text.indexOf(str, pos); + } + if (start != -1) { + sep.select(start, start + str.length()); + field.setForeground(Color.BLACK); + } else { + field.setForeground(Color.RED); + } + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void keyTyped(KeyEvent e) { } + + /** + * {@inheritDoc} + */ + @Override + public void keyPressed(KeyEvent e) { } + + /** + * Change the text where to search + */ + private void changeText() { + if (getEditor().getTextPane() != null) { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + text = doc.getText(); + if (!exact) { + text = text.toLowerCase(); + } + sep.highlightWords(field.getText(), exact); + } + } + + /** + * Inner class for the close-buttons + */ + @SuppressWarnings(value = { "serial" }) + class CloseButton extends JButton { + + /** + * Constructor + */ + CloseButton() { + super(CLOSEICON); + setFocusable(false); + setContentAreaFilled(true); + setOpaque(false); + setRolloverEnabled(true); + setBorderPainted(false); + setPreferredSize(new Dimension(BUTTONSIZE, BUTTONSIZE)); + addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + hideField(); + } + }); + } + } + + /** + * Inner class for the top-bot-buttons + @SuppressWarnings(value = { "serial" }) + */ + class TopBotButtons extends JButton { + + /** + * Constructor + * @param top true for the top-icon + */ + TopBotButtons(final boolean top) { + super(top ? TOPICON : BOTICON); + setFocusable(false); + setContentAreaFilled(true); + setOpaque(false); + setRolloverEnabled(true); + setBorderPainted(false); + setPreferredSize(new Dimension(BUTTONSIZE, BUTTONSIZE)); + addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ScilabEditorPane sep = getEditor().getTextPane(); + int pos = sep.getSelectionStart(); + int start; + String str = field.getText(); + + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + String txt = doc.getText(); + if (!exact) { + txt = txt.toLowerCase(); + } + + if (str != null) { + if (!exact) { + str = str.toLowerCase(); + } + if (top) { + start = txt.lastIndexOf(str, pos - 1); + } else { + start = txt.indexOf(str, pos + 1); + } + if (start != -1) { + sep.select(start, start + str.length()); + field.setForeground(Color.BLACK); + } else { + field.setForeground(Color.RED); + } + } + } + }); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/IndentAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/IndentAction.java new file mode 100755 index 000000000..de1f7e045 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/IndentAction.java @@ -0,0 +1,100 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.IOException; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.IndentManager; +import org.scilab.modules.scinotes.TabManager; + +/** + * IndentAction Class + * @author Bruno JOFRET + * @author Calixte DENIZET + * + */ +@SuppressWarnings("serial") +public final class IndentAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public IndentAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + int pos = sep.getCaretPosition(); + IndentManager indent = sep.getIndentManager(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + int[] ret = new int[2]; + + doc.mergeEditsBegin(); + if (start == end) { + ret = indent.indentDoc(start, end); + if (ret != null) { + sep.setCaretPosition(ret[0]); + } + } else { + ret = indent.indentDoc(start, end - 1); + if (ret != null) { + if (pos == start) { + sep.select(ret[1], ret[0]); + } else { + sep.select(ret[0], ret[1]); + } + } + } + doc.mergeEditsEnd(); + } + + /** + * @return an action to reindent a document + */ + public static SciNotes.ActionOnDocument getActionOnDocument() { + return new SciNotes.ActionOnDocument() { + public void actionOn(ScilabDocument doc) throws IOException { + IndentManager indent = new IndentManager(doc); + TabManager tab = new TabManager(doc, indent); + tab.setDefaultTabulation(); + indent.indentDoc(0, doc.getLength()); + } + }; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new IndentAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/InsertOverwriteAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/InsertOverwriteAction.java new file mode 100755 index 000000000..0019e80ba --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/InsertOverwriteAction.java @@ -0,0 +1,62 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.JComponent; +import javax.swing.KeyStroke; + +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * Handle the INSERT key + * @author Calixte DENIZET + * + */ +public final class InsertOverwriteAction extends AbstractAction { + + private static final long serialVersionUID = 8047960139101685363L; + /** + * The key associated with this action + */ + private static String key = "INSERT"; + + /** + * Constructor + */ + public InsertOverwriteAction() { } + + /** + * actionPerformed + * @param ev ActionEvent + */ + public void actionPerformed(ActionEvent ev) { + ScilabEditorPane sep = (ScilabEditorPane) ev.getSource(); + sep.setOverwriteMode(!sep.getOverwriteMode()); + if (sep.getOverwriteMode()) { + sep.setInfoBarText("Overwrite Mode"); + } else { + sep.setInfoBarText(""); + } + } + + /** + * putInInputMap + * @param textPane JComponent + */ + public static void putInInputMap(JComponent textPane) { + textPane.getInputMap().put(KeyStroke.getKeyStroke(key), new InsertOverwriteAction()); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LineBeautifierAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LineBeautifierAction.java new file mode 100755 index 000000000..eb6d8ff26 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LineBeautifierAction.java @@ -0,0 +1,81 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bernard HUGUENEY + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.event.ActionEvent; + +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorKit; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * LineBeautifierAction Class + * @author Bernard HUGUENEY + * @author Calixte DENIZET + * + */ +public final class LineBeautifierAction extends ScilabEditorKit.InsertBreakAction { + + /** + * The key associated with tthis action + */ + private static String key = "ENTER"; + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -8313095922543576108L; + + /** + * Constructor + */ + public LineBeautifierAction() { } + + /** + * actionPerformed + * @param ev ActionEvent + */ + public void actionPerformed(ActionEvent ev) { + ScilabEditorPane sep = (ScilabEditorPane) ev.getSource(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + int pos = sep.getCaretPosition(); + Element root = doc.getDefaultRootElement(); + int end = root.getElement(root.getElementIndex(pos)).getEndOffset() - 1; + String str = ""; + try { + str = doc.getText(pos, end - pos); + } catch (BadLocationException e) { + System.err.println(e); + } + if (str.matches("[ \\t]+(then|do)")) { + sep.setCaretPosition(end); + } + + super.actionPerformed(ev); + sep.getIndentManager().indentDoc(sep.getCaretPosition() - 1); + } + + /** + * putInInputMap + * @param textPane JComponent + */ + public static void putInInputMap(JComponent textPane) { + textPane.getInputMap().put(KeyStroke.getKeyStroke(key), new LineBeautifierAction()); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LineNumbersAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LineNumbersAction.java new file mode 100755 index 000000000..dcbe2b149 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LineNumbersAction.java @@ -0,0 +1,141 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.StringTokenizer; + +import javax.swing.ButtonGroup; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.commons.xml.XConfiguration; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesConfiguration; +import org.scilab.modules.scinotes.SciNotesOptions; +import org.scilab.modules.scinotes.SciNotesLineNumberPanel; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * LineNumbersAction Class + * @author Calixte DENIZET + */ +public final class LineNumbersAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -2778300710964013775L; + + private static int state; + private final JRadioButtonMenuItem[] arr = new JRadioButtonMenuItem[3]; + + /** + * Construtor + * @param name the name of the action + * @param editor SciNotes + */ + public LineNumbersAction(String name, SciNotes editor) { + super(name, editor); + init(); + } + + /** + * doAction + */ + public void doAction() { } + + private static int getState() { + return SciNotesLineNumberPanel.getState(SciNotesOptions.getSciNotesDisplay().showLineNumbers, SciNotesOptions.getSciNotesDisplay().whereami); + } + + private static void setState(int state) { + boolean[] states = SciNotesLineNumberPanel.getState(state); + SciNotesOptions.getSciNotesDisplay().showLineNumbers = states[0]; + SciNotesOptions.getSciNotesDisplay().whereami = states[1]; + XConfiguration.set(XConfiguration.getXConfigurationDocument(), SciNotesOptions.DISPLAYPATH + "/@show-line-numbers", Boolean.toString(states[0])); + XConfiguration.set(XConfiguration.getXConfigurationDocument(), SciNotesOptions.DISPLAYPATH + "/@whereami", Boolean.toString(states[1])); + SciNotes.setWhereamiLineNumbering(); + } + + private void init() { + ButtonGroup group = new ButtonGroup(); + JRadioButtonMenuItem radio; + + for (int i = 0; i < 3; i++) { + radio = createRadioButtonMenuItem(i); + group.add(radio); + arr[i] = radio; + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return createMenu + */ + public static Menu createMenu(String label, SciNotes editor, KeyStroke key) { + StringTokenizer tokens = new StringTokenizer(label, ";\uff1b"); + String labelLineNumbering = tokens.nextToken(); + String labelOff = tokens.nextToken(); + String labelNormal = tokens.nextToken(); + String labelWhereami = tokens.nextToken(); + + final LineNumbersAction ln = new LineNumbersAction(labelLineNumbering, editor); + String[] labels = new String[] {labelOff, labelNormal, labelWhereami}; + + final Menu menu = ScilabMenu.createMenu(); + menu.setText(labelLineNumbering); + + ln.arr[getState()].setSelected(true); + + for (int i = 0; i < 3; i++) { + ((JMenu) menu.getAsSimpleMenu()).add(ln.arr[i]); + ln.arr[i].setText(labels[i]); + } + + ((JMenu) menu.getAsSimpleMenu()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + ln.arr[getState()].setSelected(true); + } + }); + + return menu; + } + + /** + * createRadioButtonMenuItem + * @param ln the LineNumbersAction + * @param title the label of the menuitem + * @param state the state associated with the menuitem + * @return JRadioButtonMenuItem + */ + private static JRadioButtonMenuItem createRadioButtonMenuItem(final int state) { + JRadioButtonMenuItem radio = new JRadioButtonMenuItem(); + radio.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + LineNumbersAction.setState(state); + } + }); + + return radio; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LoadIntoScilabAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LoadIntoScilabAction.java new file mode 100755 index 000000000..a0e60978c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/LoadIntoScilabAction.java @@ -0,0 +1,136 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import javax.swing.KeyStroke; + +import org.scilab.modules.action_binding.InterpreterManagement; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * LoadIntoScilabAction class + * @author Allan CORNET + * + */ +public final class LoadIntoScilabAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -5659317486404897280L; + + private static final int MAX_LINES_RECOMMANDED = 100; + private static final int NB_STANDARD_COLUMNS = 80; + private static final int MAX_CHARACTERS_RECOMMANDED = MAX_LINES_RECOMMANDED * NB_STANDARD_COLUMNS; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public LoadIntoScilabAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + String text = getEditor().getTextPane().getText(); + + if (text.compareTo("") != 0) { + boolean bContinue = false; + + if (maxLinesRecommandedDetected(text)) { + if (ScilabModalDialog.show(getEditor(), SciNotesMessages.BIG_FILE_WARNING, SciNotesMessages.LOAD_INTO_SCILAB, + IconType.QUESTION_ICON, ButtonType.YES_NO) == AnswerOption.YES_OPTION) { + bContinue = true; + } else { + bContinue = false; + } + } else { + bContinue = true; + } + + if (bContinue) { + String tmpFilename = "LOAD_INTO_SCILAB-"; + + FileOutputStream fos = null; + OutputStreamWriter out = null; + // save file as UTF-8 + try { + File f = File.createTempFile(tmpFilename, ".sce"); + String tmpFullFilename = f.getAbsolutePath(); + fos = new FileOutputStream(f); + out = new OutputStreamWriter(fos , "UTF-8"); + out.write(text); + out.flush(); + String cmdToExec = "exec('" + tmpFullFilename + "', 1)"; + InterpreterManagement.requestScilabExec(cmdToExec); + } catch (IOException e) { + ScilabModalDialog.show(getEditor(), SciNotesMessages.COULD_NOT_FIND_TMPFILE); + } finally { + try { + if (fos != null) { + fos.close(); + } + if (out != null) { + out.close(); + } + } catch (IOException e) { } + } + } + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new LoadIntoScilabAction(label, editor), key); + } + + /** + * check if string is not too big + * @param text to scan + * @return true or false + */ + private static boolean maxLinesRecommandedDetected(String text) { + if (text.length() > MAX_CHARACTERS_RECOMMANDED) { + return true; + } + + String[] splitedStringOnLineSeparator = text.split(System.getProperty("line.separator")); + if (splitedStringOnLineSeparator.length > MAX_LINES_RECOMMANDED) { + return true; + } + + return false; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NewAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NewAction.java new file mode 100755 index 000000000..372ef1195 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NewAction.java @@ -0,0 +1,70 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * File creation management + * @author Bruno JOFRET + */ +public final class NewAction extends DefaultAction { + + private static final long serialVersionUID = -6865132453503118587L; + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public NewAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Create file action + * @see org.scilab.modules.scinotes.actions.DefaultAction#doAction() + */ + public void doAction() { + SciNotes ed = getEditor(); + ed.addEmptyTab(); + ConfigSciNotesManager.saveToOpenFiles(ed.getTextPane().getName(), ed, ed.getTextPane()); + } + + /** + * Create a menu to add to SciNotes menu bar + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new NewAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new NewAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NextParagraphAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NextParagraphAction.java new file mode 100755 index 000000000..6450d7348 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NextParagraphAction.java @@ -0,0 +1,98 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Scilab Enterprises - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.util.regex.Pattern; + +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * NextParagraphAction Class + * @author Calixte DENIZET + */ +public class NextParagraphAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + private static final Pattern pat = Pattern.compile("[ \\t\\r\\n]*"); + protected int next = +1; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public NextParagraphAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + Element root = doc.getDefaultRootElement(); + int line = root.getElementIndex(sep.getCaretPosition()); + boolean empty = isEmptyLine(doc, line); + int i = line + next; + int stop = next > 0 ? root.getElementCount() : -1; + for (; i != stop; i += next) { + boolean b = isEmptyLine(doc, i); + if (empty && !b) { + empty = false; + } else if (!empty && b) { + break; + } + } + if (i == stop) { + i = next > 0 ? stop - 1 : 0; + } + + sep.setCaretPosition(root.getElement(i).getStartOffset()); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new NextParagraphAction(label, editor), key); + } + + /** + * Test if a lin e is empty + * @param doc the document + * @param line the line number + * @return true if the line is empty + */ + private static final boolean isEmptyLine(ScilabDocument doc, int line) { + try { + Element e = doc.getDefaultRootElement().getElement(line); + int s = e.getStartOffset(); + String str = doc.getText(s, e.getEndOffset() - s); + return pat.matcher(str).matches(); + } catch (BadLocationException e) { } + + return false; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NextTabAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NextTabAction.java new file mode 100755 index 000000000..0a1610869 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/NextTabAction.java @@ -0,0 +1,60 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * NextTabAction Class + * @author Bruno JOFRET + * + */ +public final class NextTabAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 3283491475309953312L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public NextTabAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + int index = getEditor().getTabPane().getSelectedIndex(); + int count = getEditor().getTabPane().getTabCount(); + getEditor().getTabPane().setSelectedIndex((index + 1) % count); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new NextTabAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenAction.java new file mode 100755 index 000000000..c9d7af796 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenAction.java @@ -0,0 +1,116 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.File; + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser; +import org.scilab.modules.gui.filechooser.Juigetfile; +import org.scilab.modules.gui.filechooser.ScilabFileChooser; +import org.scilab.modules.gui.utils.ConfigManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * File opening management + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public class OpenAction extends DefaultAction { + + private static final long serialVersionUID = -8765712033802048782L; + private String initialDirectoryPath; + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public OpenAction(String name, SciNotes editor) { + this(name, editor, ""); + } + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + * @param path the path where to open the filechooser + */ + public OpenAction(String name, SciNotes editor, String path) { + super(name, editor); + this.initialDirectoryPath = path; + } + + /** + * Open file action + * @see org.scilab.modules.scinotes.actions.DefaultAction#doAction() + */ + public void doAction() { + String path; + if (initialDirectoryPath.length() == 0) { + path = getEditor().getTextPane().getName(); + } else { + path = initialDirectoryPath; + } + + if (path == null) { + path = ConfigManager.getLastOpenedDirectory(); + } + + String[] mask = new String[] {"*.cos*", "*.sci", "*.sce", "*.tst", "*.start", "*.quit", "*.dem", "*.sc*", "all"}; + + SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser()); + fileChooser.setMultiSelectionEnabled(true); + fileChooser.setInitialDirectory(path); + fileChooser.setAcceptAllFileFilterUsed(true); + fileChooser.addMask(mask, null); + fileChooser.setUiDialogType(Juigetfile.SAVE_DIALOG); + + int retval = fileChooser.showOpenDialog(getEditor()); + if (retval == JFileChooser.APPROVE_OPTION) { + File[] f = fileChooser.getSelectedFiles(); + for (int i = 0; i < f.length; i++) { + RecentFileAction.updateRecentOpenedFilesMenu(getEditor()); + getEditor().readFile(f[i]); + } + } + } + + /** + * Create a menu to add to SciNotes menu bar + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static Object createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new OpenAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new OpenAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenFileInAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenFileInAction.java new file mode 100755 index 000000000..da8425cd3 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenFileInAction.java @@ -0,0 +1,115 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.File; +import java.util.List; +import java.util.StringTokenizer; + +import javax.swing.JButton; +import javax.swing.KeyStroke; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.bridge.menu.SwingScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * Action to open the filechooser in a predefined directory + * @author Calixte DENIZET + */ +public final class OpenFileInAction extends OpenAction { + + private static final long serialVersionUID = 1L; + private static final String SCI = "SCI"; + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public OpenFileInAction(String name, SciNotes editor) { + super(name, editor, name); + } + + /** + * Create a menu to add to SciNotes menu bar + * @param editor associated SciNotes instance + * @param path the path to open + * @return the menuitem + */ + public static MenuItem createMenu(SciNotes editor, String path) { + return createMenu(path, null, new OpenFileInAction(path, editor), null); + } + + /** + * Create a menu to add to SciNotes menu bar + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static Object createMenu(String label, final SciNotes editor, KeyStroke key) { + final Menu favoriteDirs = ScilabMenu.createMenu(); + ((SwingScilabMenu) favoriteDirs.getAsSimpleMenu()).addMenuListener(new MenuListener() { + + public void menuCanceled(MenuEvent e) { } + public void menuDeselected(MenuEvent e) { } + public void menuSelected(MenuEvent e) { + updateFavoriteDirsMenu(favoriteDirs, editor); + } + }); + + favoriteDirs.setText(label); + updateFavoriteDirsMenu(favoriteDirs, editor); + return favoriteDirs; + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + StringTokenizer token = new StringTokenizer(tooltip, ";\uff1b"); + String tt = token.nextToken(); + String path = token.nextToken(); + if (path.equals(SCI)) { + path = System.getenv(SCI); + } else if (path.equals("MODULES")) { + path = System.getenv(SCI) + "/modules"; + } + + return createButton(tt + path, icon, new OpenFileInAction(path, editor)); + } + + /** + * Update menu displaying favorite directories. + * @param menu the menu to update + * @param editor SciNotes + */ + public static void updateFavoriteDirsMenu(Menu menu, SciNotes editor) { + ((SwingScilabMenu) menu.getAsSimpleMenu()).removeAll(); + List<File> dirs = ConfigSciNotesManager.getAllFavoriteDirs(); + + for (int i = 0; i < dirs.size(); i++) { + menu.add(createMenu(editor, dirs.get(i).getPath())); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenSourceFileOnKeywordAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenSourceFileOnKeywordAction.java new file mode 100755 index 000000000..0bdf4cbb3 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenSourceFileOnKeywordAction.java @@ -0,0 +1,343 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.util.Iterator; +import java.util.NavigableSet; +import java.util.Set; +import java.util.TreeSet; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; + +import org.scilab.modules.action_binding.InterpreterManagement; +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.KeywordEvent; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabLexer; +import org.scilab.modules.scinotes.ScilabLexerConstants; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * OpenSourceFileOnKeywordAction Class + * @author Calixte DENIZET + */ +public class OpenSourceFileOnKeywordAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + + private static final int GAP = 5; + private static boolean windowAlreadyExist; + private static JFrame mainFrame; + + private NavigableSet<String> macrosSet; + private JButton okButton; + private JButton cancelButton; + private JComboBox comboComplete; + private boolean onMenu; + private int lastSize; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public OpenSourceFileOnKeywordAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + * @param onMenu if true the dialog will be open when a menu is actionned + */ + public OpenSourceFileOnKeywordAction(String name, SciNotes editor, boolean onMenu) { + this(name, editor); + this.onMenu = onMenu; + } + + /** + * Clean + */ + public static void close() { + mainFrame = null; + } + + /** + * doAction + */ + @Override + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + KeywordEvent kwe = sep.getKeywordEvent(sep.getSelectionEnd()); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + if (ScilabLexerConstants.isOpenable(kwe.getType())) { + String name = ""; + try { + name = doc.getText(kwe.getStart(), kwe.getLength()); + } catch (BadLocationException e) { } + if (onMenu) { + openSourceBox(name); + } else { + openSource(name); + } + } else { + openSourceBox(""); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new OpenSourceFileOnKeywordAction(label, editor, true), key); + } + + /** + * Show the source of a macro if it is present in the pane or open the source + * @param pane the ScilabEditorPane + * @param name the macro's name + */ + public static void openSource(ScilabEditorPane pane, String name) { + ScilabDocument doc = (ScilabDocument) pane.getDocument(); + int pos = doc.searchFunctionByName(name); + if (pos != -1) { + pane.scrollTextToPos(pos); + } else { + String path = "get_function_path('" + name + "')"; + InterpreterManagement.requestScilabExec("if " + path + " ~=[] then editor(" + path + ");end"); + } + } + + /** + * Close the window + */ + public static void closeOpenSourceWindow() { + if (windowAlreadyExist) { + mainFrame.dispose(); + windowAlreadyExist = false; + } + } + + /** + * Open a window to get the name of the macro + * @param name the name of a macro + */ + public void openSourceBox(String name) { + if (windowAlreadyExist) { + mainFrame.setVisible(true); + if (name.length() != 0) { + comboComplete.removeAllItems(); + comboComplete.getEditor().setItem(name); + comboComplete.hidePopup(); + } + return; + } + + macrosSet = new TreeSet(ScilabLexer.macros); + + mainFrame = new JFrame(); + mainFrame.setAlwaysOnTop(true); + mainFrame.setIconImage(new ImageIcon(FindIconHelper.findIcon("scilab")).getImage()); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + windowAlreadyExist = true; + + JLabel label = new JLabel(SciNotesMessages.OPEN_SOURCE_FILE_OF); + + comboComplete = new JComboBox(); + comboComplete.setEditable(true); + if (name.length() != 0) { + comboComplete.removeAllItems(); + comboComplete.getEditor().setItem(name); + } else { + updateComboComplete(" "); + } + + comboComplete.hidePopup(); + + cancelButton = new JButton(SciNotesMessages.CANCEL); + okButton = new JButton(SciNotesMessages.OK); + okButton.setPreferredSize(cancelButton.getPreferredSize()); + + JPanel panelButton = new JPanel(); + panelButton.setLayout(new GridLayout(1, 4, GAP, GAP)); + panelButton.setBorder(BorderFactory.createEmptyBorder(GAP, 0, 0, 0)); + panelButton.add(new JLabel()); + panelButton.add(new JLabel()); + panelButton.add(cancelButton); + panelButton.add(okButton); + + JPanel panelCombo = new JPanel(); + panelCombo.setLayout(new GridLayout(1, 2, GAP, GAP)); + panelCombo.add(label); + panelCombo.add(comboComplete); + + JPanel panelFrame = new JPanel(); + panelFrame.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); + panelFrame.setLayout(new BoxLayout(panelFrame, BoxLayout.PAGE_AXIS)); + panelFrame.add(panelCombo); + panelFrame.add(panelButton); + + mainFrame.setContentPane(panelFrame); + + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + OpenSourceFileOnKeywordAction.windowAlreadyExist = false; + mainFrame.dispose(); + } + }); + + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + OpenSourceFileOnKeywordAction.windowAlreadyExist = false; + mainFrame.dispose(); + openSource((String) comboComplete.getEditor().getItem()); + } + }); + + comboComplete.getEditor().getEditorComponent().addKeyListener(new KeyListener() { + + private String old = ""; + + @Override + public void keyReleased(KeyEvent e) { + int code = e.getKeyCode(); + if (code == KeyEvent.VK_ENTER) { + if (comboComplete.getSelectedIndex() == -1 && comboComplete.getItemCount() > 0) { + comboComplete.setSelectedIndex(0); + } + comboComplete.hidePopup(); + okButton.requestFocus(); + } else if (code == KeyEvent.VK_ESCAPE) { + comboComplete.hidePopup(); + } else if (code != KeyEvent.VK_UP && code != KeyEvent.VK_DOWN) { + updateComboComplete(old); + comboComplete.setPopupVisible(true); + } + } + + @Override + public void keyPressed(KeyEvent arg0) { + old = (String) comboComplete.getEditor().getItem(); + } + + @Override + public void keyTyped(KeyEvent arg0) { } + }); + + mainFrame.addWindowListener(new WindowListener() { + @Override + public void windowClosed(WindowEvent arg0) { } + @Override + public void windowDeiconified(WindowEvent arg0) { } + @Override + public void windowActivated(WindowEvent arg0) { } + + @Override + public void windowClosing(WindowEvent arg0) { + OpenSourceFileOnKeywordAction.windowAlreadyExist = false; + mainFrame.dispose(); + } + + @Override + public void windowDeactivated(WindowEvent arg0) { } + @Override + public void windowIconified(WindowEvent arg0) { }; + @Override + public void windowOpened(WindowEvent arg0) { } + }); + + mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + mainFrame.setTitle(SciNotesMessages.OPEN_SOURCE); + mainFrame.pack(); + mainFrame.setLocationRelativeTo(getEditor()); + mainFrame.setVisible(true); + } + + /** + * Open the source of a macro + * @param name of the macro + */ + private void openSource(String name) { + openSource(getEditor().getTextPane(), name); + } + + /** + * Update the comboBox with the possible completion of the name + * entered in the comboBox. + * @param old the previous name + */ + private void updateComboComplete(String old) { + String name = (String) comboComplete.getEditor().getItem(); + Set subset = null; + if (name != null && !name.equals(old)) { + String bound = ""; + Iterator<String> iter; + int len = name.length(); + if (len != 0) { + if (len == 1) { + bound = new String(new char[] {(char) (name.charAt(0) + 1)}); + } else { + bound = name.substring(0, len - 1); + bound += (char) (name.charAt(len - 1) + 1); + } + /* If "abc" is entered, we built "abd" (last letter + 1) and we + retrieve all the names between "abc" and "abd" (excluded) */ + subset = macrosSet.subSet(name, true, bound, false); + iter = subset.iterator(); + } else { + iter = macrosSet.iterator(); + } + + if (subset != null && subset.size() != lastSize) { + comboComplete.removeAllItems(); + while (iter.hasNext()) { + comboComplete.addItem(iter.next()); + } + lastSize = subset.size(); + comboComplete.setPopupVisible(false); + } + + comboComplete.getEditor().setItem(name); + JTextComponent c = ((JTextComponent) comboComplete.getEditor().getEditorComponent()); + c.setSelectionStart(c.getSelectionEnd()); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenTabInNewWindowAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenTabInNewWindowAction.java new file mode 100755 index 000000000..bf25af8ef --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenTabInNewWindowAction.java @@ -0,0 +1,53 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * Open a tab in a new window + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class OpenTabInNewWindowAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor associated editor + */ + public OpenTabInNewWindowAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new OpenTabInNewWindowAction(label, editor), key); + } + + /** + * Action + */ + public void doAction() { + SciNotes.cloneAndCloseCurrentTab(getEditor(), false); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenURLAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenURLAction.java new file mode 100755 index 000000000..f0e822ffd --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OpenURLAction.java @@ -0,0 +1,83 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.utils.WebBrowser; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabLexerConstants; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.KeywordEvent; + +/** + * OpenURLAction Class + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class OpenURLAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public OpenURLAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + KeywordEvent kwe = sep.getKeywordEvent(sep.getSelectionEnd()); + if (ScilabLexerConstants.URL == kwe.getType() || ScilabLexerConstants.MAIL == kwe.getType()) { + try { + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + String url = doc.getText(kwe.getStart(), kwe.getLength()); + WebBrowser.openUrl(url); + } catch (BadLocationException e) { } + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + final MenuItem menuitem = createMenu(label, null, new OpenURLAction(label, editor), key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + String keyword = editor.getTextPane().getSelectedText(); + if (keyword == null) { + KeywordEvent kwe = editor.getTextPane().getKeywordEvent(); + menuitem.setEnabled(ScilabLexerConstants.MAIL == kwe.getType() || ScilabLexerConstants.URL == kwe.getType()); + } + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OverwriteAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OverwriteAction.java new file mode 100755 index 000000000..073bfb07a --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/OverwriteAction.java @@ -0,0 +1,67 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * OverwriteAction class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class OverwriteAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public OverwriteAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Create Menu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + final MenuItem menuitem = createMenu(label, null, new OverwriteAction(label, editor), key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + menuitem.setEnabled(editor.getTextPane().checkExternalModif()); + } + } + }); + + return menuitem; + } + + /** + * DoAction + */ + public void doAction() { + getEditor().overwrite(getEditor().getTabPane().getSelectedIndex()); + getEditor().getTextPane().updateInfosWhenFocused(); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PageSetupAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PageSetupAction.java new file mode 100755 index 000000000..b3631a3ae --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PageSetupAction.java @@ -0,0 +1,74 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.print.PageFormat; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * Class Page setup action for SciNotes + * @author Sylvestre Koumar + * + */ +@SuppressWarnings(value = { "serial" }) +public class PageSetupAction extends DefaultAction { + + private static PageFormat pageFormat; + + static { + pageFormat = new PageFormat(); + pageFormat.setPaper(ConfigSciNotesManager.getPaperFormat()); + } + + /** + * Default constructor + * @param name the name of the action + * @param editor Editor + */ + public PageSetupAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Function Run + */ + public void doAction() { + pageFormat = PrinterJob.getPrinterJob().pageDialog(pageFormat); + ConfigSciNotesManager.savePaperFormat(pageFormat.getPaper()); + } + + /** + * Create the MenuItem for page setup action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PageSetupAction(label, editor), key); + } + + /** + * Get the page format + * @return PageFormat + */ + public static PageFormat getPageFormat() { + return pageFormat; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PasteAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PasteAction.java new file mode 100755 index 000000000..61c6ce86c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PasteAction.java @@ -0,0 +1,91 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.io.StringReader; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesCaret; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorKit; + +/** + * Class for paste action + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class PasteAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor to associate + */ + public PasteAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Action ! + */ + public void doAction() { + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + try { + String str = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getContents(this).getTransferData(DataFlavor.stringFlavor); + if (str != null && !str.isEmpty()) { + str = ((ScilabEditorKit) getEditor().getEditorKit()).read(new StringReader(str)).content; + doc.mergeEditsBegin(); + getEditor().getTextPane().replaceSelection(str); + doc.mergeEditsEnd(); + if (!((SciNotesCaret) getEditor().getTextPane().getCaret()).isEmptySelection()) { + ((SciNotesCaret) getEditor().getTextPane().getCaret()).removeHighlights(); + } + } + } catch (UnsupportedFlavorException e) { + } catch (IOException e) { + System.err.println(e); + } + } + + /** + * Create the MenuItem for print action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PasteAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new PasteAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PasteColumnAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PasteColumnAction.java new file mode 100755 index 000000000..5258e22c4 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PasteColumnAction.java @@ -0,0 +1,138 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.io.StringReader; +import java.util.StringTokenizer; + +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.CompoundUndoManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesCaret; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorKit; + +/** + * Class for paste action + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class PasteColumnAction extends DefaultAction { + + private static final String CR = "\n"; + + /** + * Constructor + * @param name the name of the action + * @param editor to associate + */ + public PasteColumnAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Action ! + */ + public void doAction() { + ScilabDocument doc = (ScilabDocument) getEditor().getTextPane().getDocument(); + Element root = doc.getDefaultRootElement(); + String str = null; + try { + str = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getContents(this).getTransferData(DataFlavor.stringFlavor); + if (str != null) { + str = ((ScilabEditorKit) getEditor().getEditorKit()).read(new StringReader(str)).content; + } + } catch (UnsupportedFlavorException ex1) { + System.err.println(ex1); + } catch (IOException ex2) { + System.err.println(ex2); + } + if (str != null) { + SciNotesCaret caret = (SciNotesCaret) getEditor().getTextPane().getCaret(); + int pos; + if (caret.isEmptySelection()) { + pos = getEditor().getTextPane().getSelectionStart(); + } else { + int[][] positions = caret.getSelectedPositions(); + pos = positions[0][0]; + } + int spos = pos; + doc.getUndoManager().enableOneShot(true); + doc.mergeEditsBegin(); + getEditor().getTextPane().replaceSelection(""); + StringTokenizer tokens = new StringTokenizer(str, CR); + int index = root.getElementIndex(pos); + String crs = initString(tokens.countTokens() - root.getElementCount() + index, '\n'); + if (crs.length() > 0) { + try { + doc.insertString(doc.getLength(), crs, null); + } catch (BadLocationException e) { } + } + int col = pos - root.getElement(index).getStartOffset(); + while (tokens.hasMoreTokens()) { + String tok = tokens.nextToken(); + int end = root.getElement(index).getEndOffset() - 1; + if (pos > end) { + tok = initString(pos - end, ' ') + tok; + pos = end; + } + try { + doc.insertString(pos, tok, null); + } catch (BadLocationException e) { } + if (index < root.getElementCount() - 1) { + pos = root.getElement(++index).getStartOffset() + col; + } + } + doc.mergeEditsEnd(); + doc.getUndoManager().enableOneShot(false); + getEditor().getTextPane().setCaretPosition(spos); + } + } + + /** + * Init a string + * @param n the length of the string + * @param c the char to use to initialize + * @return the initialized string + */ + private static String initString(int n, char c) { + if (n > 0) { + char[] buf = new char[n]; + for (int i = 0; i < n; i++) { + buf[i] = c; + } + + return new String(buf); + } + return ""; + } + + /** + * Create the MenuItem for print action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PasteColumnAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PreviousParagraphAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PreviousParagraphAction.java new file mode 100755 index 000000000..f449984d4 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PreviousParagraphAction.java @@ -0,0 +1,48 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Scilab Enterprises - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * PreviousParagraphAction Class + * @author Calixte DENIZET + */ +public class PreviousParagraphAction extends NextParagraphAction { + + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public PreviousParagraphAction(String name, SciNotes editor) { + super(name, editor); + next = -1; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PreviousParagraphAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PreviousTabAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PreviousTabAction.java new file mode 100755 index 000000000..e275b562c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PreviousTabAction.java @@ -0,0 +1,56 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * Class Previous tab action for SciNotes + * @author Sylvestre Koumar + * + */ +@SuppressWarnings(value = { "serial" }) +public class PreviousTabAction extends DefaultAction { + + /** + * Default constructor + * @param name the name of the action + * @param editor Editor + */ + public PreviousTabAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + int index = getEditor().getTabPane().getSelectedIndex(); + int count = getEditor().getTabPane().getTabCount(); + getEditor().getTabPane().setSelectedIndex((count + index - 1) % count); + } + + /** + * Create the MenuItem for previous tab action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PreviousTabAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PrintAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PrintAction.java new file mode 100755 index 000000000..59a42fbc7 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PrintAction.java @@ -0,0 +1,77 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.jvm.LoadClassPath; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.CodeExporter; + +/** + * Class Print action for SciNotes + * @author Sylvestre Koumar + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class PrintAction extends DefaultAction { + + private boolean codeConverterLoaded; + + /** + * Default constructor + * @param name the name of the action + * @param editor the editor + */ + public PrintAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Function doAction + */ + public void doAction() { + if (!codeConverterLoaded) { + LoadClassPath.loadOnUse("copyAsHTMLinScinotes"); + LoadClassPath.loadOnUse("pdf_ps_eps_graphic_export"); + codeConverterLoaded = true; + } + ScilabEditorPane pane = getEditor().getTextPane(); + CodeExporter.convert(pane, null, CodeExporter.PRINT, PageSetupAction.getPageFormat()); + } + + /** + * Create the MenuItem for print action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PrintAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new PrintAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PrintPreviewAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PrintPreviewAction.java new file mode 100755 index 000000000..f509ae504 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/PrintPreviewAction.java @@ -0,0 +1,81 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.jvm.LoadClassPath; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.CodeExporter; + +/** + * PrintPreviewAction class + * @author Bruno JOFRET + * + */ +public final class PrintPreviewAction extends DefaultAction { + + private boolean codeConverterLoaded; + + /** + * serialVersionUID + */ + private static final long serialVersionUID = -3222532237364937814L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public PrintPreviewAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + if (!codeConverterLoaded) { + LoadClassPath.loadOnUse("copyAsHTMLinScinotes"); + LoadClassPath.loadOnUse("pdf_ps_eps_graphic_export"); + codeConverterLoaded = true; + } + ScilabEditorPane pane = getEditor().getTextPane(); + CodeExporter.convert(pane, null, CodeExporter.PREVIEW, PageSetupAction.getPageFormat()); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new PrintPreviewAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new PrintPreviewAction(tooltip, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RecentFileAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RecentFileAction.java new file mode 100755 index 000000000..0f9b38d5f --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RecentFileAction.java @@ -0,0 +1,126 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - INRIA - Allan SIMON + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.bridge.menu.SwingScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesOptions; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + + +/** + * RecentFileAction Class + * @author Allan SIMON + * + */ +@SuppressWarnings(value = { "serial" }) +public class RecentFileAction extends DefaultAction { + + private static Map<SciNotes, Menu> menus = new HashMap<SciNotes, Menu>(); + + private File recentFile; + + /** + * Constructor + * @param editor SciNotes + * @param f File + */ + public RecentFileAction(SciNotes editor , File f) { + super(f.getName(), editor); + recentFile = f; + } + + /** + * doAction + */ + public void doAction() { + ConfigSciNotesManager.saveToRecentOpenedFiles(recentFile.getPath()); + getEditor().readFile(recentFile); + getEditor().setTitle(recentFile.getPath() + " - SciNotes"); + } + + /** + * Clean + */ + public static void close(SciNotes ed) { + menus.remove(ed); + } + + /** + * createMenu + * @param editor SciNotes + * @param f File + * @return a MenuItem + */ + public static MenuItem createMenu(SciNotes editor, File f) { + return createMenu(f.getName(), null, new RecentFileAction(editor, f), null); + } + + /** + * createMenu + * @param label label of the menu + * @param editor associated editor + * @param key KeyStroke + * @return the menu + */ + public static Menu createMenu(String label, SciNotes editor, KeyStroke key) { + Menu recentsMenu = ScilabMenu.createMenu(); + recentsMenu.setText(label); + menus.put(editor, recentsMenu); + + updateRecentOpenedFilesMenu(editor); + return recentsMenu; + } + + /** + * Update menu displaying recent opened files. + * @param editor SciNotes + */ + public static void updateRecentOpenedFilesMenu() { + List<File> recentFiles = ConfigSciNotesManager.getAllRecentOpenedFiles(); + for (SciNotes ed : menus.keySet()) { + Menu recentsMenu = menus.get(ed); + if (recentsMenu != null) { + ((SwingScilabMenu) recentsMenu.getAsSimpleMenu()).removeAll(); + final int N = Math.min(recentFiles.size(), SciNotesOptions.getSciNotesPreferences().numberOfRecentlyOpen); + for (int i = N - 1; i >= 0; i--) { + recentsMenu.add(RecentFileAction.createMenu(ed, recentFiles.get(i))); + } + } + } + } + + /** + * Update menu displaying recent opened files. + * @param editor SciNotes + */ + public static void updateRecentOpenedFilesMenu(SciNotes editor) { + List<File> recentFiles = ConfigSciNotesManager.getAllRecentOpenedFiles(); + Menu recentsMenu = menus.get(editor); + if (recentsMenu != null) { + ((SwingScilabMenu) recentsMenu.getAsSimpleMenu()).removeAll(); + final int N = Math.min(recentFiles.size(), SciNotesOptions.getSciNotesPreferences().numberOfRecentlyOpen); + for (int i = N - 1; i >= 0; i--) { + recentsMenu.add(RecentFileAction.createMenu(editor, recentFiles.get(i))); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RedoAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RedoAction.java new file mode 100755 index 000000000..98d3ce681 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RedoAction.java @@ -0,0 +1,68 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * CommentAction Class + * @author Bruno JOFRET + * + */ +@SuppressWarnings(value = { "serial" }) +public class RedoAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public RedoAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + getEditor().redo(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new RedoAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + JButton button = createButton(tooltip, icon, new RedoAction(tooltip, editor)); + editor.setRedoButton(button); + return button; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RegisterFavoriteDirsAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RegisterFavoriteDirsAction.java new file mode 100755 index 000000000..ddeff555b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RegisterFavoriteDirsAction.java @@ -0,0 +1,214 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.File; +import java.util.List; +import java.util.StringTokenizer; + +import javax.swing.JFileChooser; +import javax.swing.KeyStroke; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +import org.scilab.modules.gui.filechooser.ScilabFileChooser; +import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.bridge.menu.SwingScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * Action to register favorite directories + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class RegisterFavoriteDirsAction extends DefaultAction { + + private static MenuItem addDir; + private static MenuItem rmDir; + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public RegisterFavoriteDirsAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Clean + */ + public static void close() { + addDir = null; + rmDir = null; + } + + /** + * Create a menu to add to SciNotes menu bar + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static Object createMenu(String label, final SciNotes editor, KeyStroke key) { + StringTokenizer token = new StringTokenizer(label, ";\uff1b"); + String label1 = token.nextToken(); + String label2 = token.nextToken(); + String label3 = token.nextToken(); + + final Menu favoriteDirs = ScilabMenu.createMenu(); + ((SwingScilabMenu) favoriteDirs.getAsSimpleMenu()).addMenuListener(new MenuListener() { + + public void menuCanceled(MenuEvent e) { } + public void menuDeselected(MenuEvent e) { } + public void menuSelected(MenuEvent e) { + updateFavoriteDirsMenu(favoriteDirs, editor); + } + }); + + favoriteDirs.setText(label1); + addDir = AddDirectoryAction.createMenu(favoriteDirs, label2, editor, null); + rmDir = RmDirectoryAction.createMenu(favoriteDirs, label3, editor, null); + updateFavoriteDirsMenu(favoriteDirs, editor); + return favoriteDirs; + } + + /** + * Create a menu to add to SciNotes menu bar + * @param editor associated SciNotes instance + * @param path the path to open + * @return the menuitem + */ + public static MenuItem createMenu(SciNotes editor, String path) { + return createMenu(path, null, new DefaultAction("", editor) { + public void doAction() { } + }, null); + } + + /** + * Update menu displaying favorite directories. + * @param menu the menu to update + * @param editor SciNotes + */ + public static void updateFavoriteDirsMenu(Menu menu, SciNotes editor) { + ((SwingScilabMenu) menu.getAsSimpleMenu()).removeAll(); + menu.add(addDir); + menu.add(rmDir); + + List<File> dirs = ConfigSciNotesManager.getAllFavoriteDirs(); + + if (dirs.size() != 0) { + menu.addSeparator(); + } + + for (int i = 0; i < dirs.size(); i++) { + menu.add(createMenu(editor, dirs.get(i).getPath())); + } + } + + /** + * Inner class to handle the action which consists to add a new directory + */ + @SuppressWarnings(value = { "serial" }) + static class AddDirectoryAction extends DefaultAction { + + private Menu menu; + + /** + * Constructor + * @param menu the menu associated with this action + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public AddDirectoryAction(Menu menu, String name, SciNotes editor) { + super(name, editor); + this.menu = menu; + } + + /** + * Open file action + * @see org.scilab.modules.scinotes.actions.DefaultAction#doAction() + */ + public void doAction() { + SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser()); + fileChooser.setDialogTitle(getCommand()); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setAcceptAllFileFilterUsed(false); + if (fileChooser.showOpenDialog(getEditor()) == JFileChooser.APPROVE_OPTION) { + File path = fileChooser.getSelectedFile(); + if (path == null || path.isFile()) { + path = fileChooser.getCurrentDirectory(); + } + ConfigSciNotesManager.saveFavoriteDirectory(path.getPath()); + updateFavoriteDirsMenu(menu, getEditor()); + } + } + + /** + * Create a menu to add to SciNotes menu bar + * @param menu the menu associated with this action + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static MenuItem createMenu(Menu menu, String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new AddDirectoryAction(menu, label, editor), key); + } + } + + /** + * Inner class to handle the action which consists to remove a directory + @SuppressWarnings(value = { "serial" }) + */ + static class RmDirectoryAction extends DefaultAction { + + private Menu menu; + + /** + * Constructor + * @param menu the menu associated with this action + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public RmDirectoryAction(Menu menu, String name, SciNotes editor) { + super(name, editor); + this.menu = menu; + } + + /** + * Open file action + * @see org.scilab.modules.scinotes.actions.DefaultAction#doAction() + */ + public void doAction() { + ConfigSciNotesManager.rmLastFavoriteDirectory(); + updateFavoriteDirsMenu(menu, getEditor()); + } + + /** + * Create a menu to add to SciNotes menu bar + * @param menu the menu associated with this action + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static MenuItem createMenu(Menu menu, String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new RmDirectoryAction(menu, label, editor), key); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ReloadAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ReloadAction.java new file mode 100755 index 000000000..a52865d78 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ReloadAction.java @@ -0,0 +1,55 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * ReloadAction class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class ReloadAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ReloadAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Create Menu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new ReloadAction(label, editor), key); + } + + /** + * DoAction + */ + public void doAction() { + getEditor().reload(getEditor().getTabPane().getSelectedIndex()); + getEditor().getTextPane().updateInfosWhenFocused(); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RemoveAnchorAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RemoveAnchorAction.java new file mode 100755 index 000000000..ebcdf1a8c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RemoveAnchorAction.java @@ -0,0 +1,65 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * RemoveAnchorAction Class + * @author Calixte DENIZET + */ +public class RemoveAnchorAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public RemoveAnchorAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + Element root = doc.getDefaultRootElement(); + ScilabDocument.ScilabLeafElement line = (ScilabDocument.ScilabLeafElement) root.getElement(root.getElementIndex(sep.getCaretPosition())); + line.setAnchor(null); + sep.getXln().repaint(); + if (getEditor().getNavigator() != null) { + getEditor().getNavigator().update(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new RemoveAnchorAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RemoveTrailingWhiteAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RemoveTrailingWhiteAction.java new file mode 100755 index 000000000..f2a1b0b1b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RemoveTrailingWhiteAction.java @@ -0,0 +1,93 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import java.io.IOException; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.TrailingWhiteManager; + +/** + * RemoveTrailingWhiteAction Class + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class RemoveTrailingWhiteAction extends DefaultAction { + + /** + * Construtor + * @param name the name of the action + * @param editor SciNotes + */ + public RemoveTrailingWhiteAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + int pos = sep.getCaretPosition(); + TrailingWhiteManager trailing = sep.getTrailingWhiteManager(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + + doc.mergeEditsBegin(); + if (start == end) { + int ret = trailing.removeTrailingWhite(start); + if (ret != -1) { + sep.setCaretPosition(ret); + } + } else { + int[] ret = new int[2]; + ret = trailing.removeTrailingWhite(start, end - 1); + if (ret != null) { + if (pos == start) { + sep.select(ret[1], ret[0]); + } else { + sep.select(ret[0], ret[1]); + } + } + } + doc.mergeEditsEnd(); + } + + /** + * @return an action to reindent a document + */ + public static SciNotes.ActionOnDocument getActionOnDocument() { + return new SciNotes.ActionOnDocument() { + public void actionOn(ScilabDocument doc) throws IOException { + TrailingWhiteManager trailingWhite = new TrailingWhiteManager(doc); + trailingWhite.removeTrailingWhite(0, doc.getLength()); + } + }; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new RemoveTrailingWhiteAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RepeatSelectionOnColumnAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RepeatSelectionOnColumnAction.java new file mode 100755 index 000000000..11d782810 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RepeatSelectionOnColumnAction.java @@ -0,0 +1,123 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * Class for paste action + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class RepeatSelectionOnColumnAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor to associate + */ + public RepeatSelectionOnColumnAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Action ! + */ + public void doAction() { + ScilabEditorPane pane = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) pane.getDocument(); + Element root = doc.getDefaultRootElement(); + String str = null; + boolean select = false; + + if (pane.getSelectionStart() == pane.getSelectionEnd()) { + try { + str = doc.getText(pane.getCaretPosition(), 1); + } catch (BadLocationException e) { } + } else { + str = pane.getSelectedText(); + select = true; + } + + if (str != null) { + doc.mergeEditsBegin(); + int pos = pane.getSelectionStart(); + int index = root.getElementIndex(pos); + int col = pos - root.getElement(index).getStartOffset(); + int len = str.length(); + String cr = ""; + int end; + int spos = 0; + if (index < root.getElementCount() - 1) { + pos = root.getElement(index + 1).getStartOffset() + col; + end = root.getElement(index + 1).getEndOffset() - 1; + } else { + cr = "\n"; + spos = 1; + end = root.getElement(index).getEndOffset() - 1; + pos = end + col; + } + + spos += pos; + if (pos >= end) { + str = cr + whites(pos - end) + str; + pos = end; + } + try { + doc.insertString(pos, str, null); + } catch (BadLocationException e) { } + + doc.mergeEditsEnd(); + if (select) { + pane.select(spos, spos + len); + } else { + pane.setCaretPosition(spos); + } + } + } + + /** + * Generates a string of whites + * @param n the whites number + * @param the string + */ + private static String whites(int n) { + if (n > 0) { + char[] buf = new char[n]; + for (int i = 0; i < n; i++) { + buf[i] = ' '; + } + + return new String(buf); + } + return ""; + } + + /** + * Create the MenuItem for print action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new RepeatSelectionOnColumnAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RestoreOpenedFilesAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RestoreOpenedFilesAction.java new file mode 100755 index 000000000..6ea17ae75 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/RestoreOpenedFilesAction.java @@ -0,0 +1,577 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Paul Griffiths + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.EventObject; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.Vector; + +import javax.swing.AbstractAction; +import javax.swing.AbstractCellEditor; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.checkboxmenuitem.CheckBoxMenuItem; +import org.scilab.modules.gui.bridge.menubar.SwingScilabMenuBar; +import org.scilab.modules.gui.bridge.toolbar.SwingScilabToolBar; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * RestoreOpenedFilesAction Class + * @author Paul Griffiths + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class RestoreOpenedFilesAction extends DefaultCheckAction { + + private static final int GAP = 10; + private static final String ESCAPE = "ESCAPE"; + private static final Icon SCILAB_ICON = new ImageIcon(FindIconHelper.findIcon("scilab")); + private static List<File> selectedFiles; + private static Map<SciNotes, List<Component>> listOfComponents; + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public RestoreOpenedFilesAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + ConfigSciNotesManager.saveRestoreOpenedFiles(this.getState()); + } + + /** + * Create a menu to add to SciNotes menu bar + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static CheckBoxMenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + CheckBoxMenuItem cb = createCheckBoxMenu(label, null, new RestoreOpenedFilesAction(label, editor), key); + boolean b = ConfigSciNotesManager.getRestoreOpenedFiles(); + cb.setChecked(b); + return cb; + } + + /** + * @return the selected files opened in the last session + */ + public static List<File> getSelectedFiles() { + return selectedFiles; + } + + private static void saveEnabledComponents(SciNotes ed) { + List<Component> list = new ArrayList<Component>(); + SwingScilabMenuBar mb = (SwingScilabMenuBar) ed.getMenuBar().getAsSimpleMenuBar(); + SwingScilabToolBar tb = (SwingScilabToolBar) ed.getToolBar().getAsSimpleToolBar(); + for (int i = 0; i < mb.getMenuCount(); i++) { + if (mb.getMenu(i).isEnabled()) { + list.add(mb.getMenu(i)); + mb.getMenu(i).setEnabled(false); + } + } + for (int i = 0; i < tb.getComponentCount(); i++) { + if (tb.getComponent(i).isEnabled()) { + list.add(tb.getComponent(i)); + tb.getComponent(i).setEnabled(false); + } + } + + if (listOfComponents == null) { + listOfComponents = new HashMap<SciNotes, List<Component>>(); + } + listOfComponents.put(ed, list); + } + + public static void restoreEnabledComponents(SciNotes ed) { + if (listOfComponents != null && listOfComponents.containsKey(ed)) { + SwingScilabMenuBar mb = (SwingScilabMenuBar) ed.getMenuBar().getAsSimpleMenuBar(); + SwingScilabToolBar tb = (SwingScilabToolBar) ed.getToolBar().getAsSimpleToolBar(); + List<Component> l = listOfComponents.get(ed); + for (Component c : l) { + c.setEnabled(true); + } + + l.clear(); + listOfComponents.remove(ed); + if (listOfComponents.isEmpty()) { + listOfComponents = null; + } + } + } + + public static JPanel getTab(final SciNotes ed, final String uuid) { + final JTree tree = fillTree(uuid); + if (tree == null) { + return null; + } + + JButton ok = new JButton(SciNotesMessages.OK); + JButton cancel = new JButton(SciNotesMessages.CANCEL); + ok.setPreferredSize(cancel.getPreferredSize()); + Object[] buttons = new Object[2]; + ok.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + List<File> list = getOpenedFiles(tree, uuid); + ed.getTabPane().remove(0); + if (list != null && list.size() != 0) { + for (File f : list) { + ed.openFile(f.getPath(), 0, null); + } + } else if (ed.getTabPane().getTabCount() == 0) { + ed.addEmptyTab(); + } + + if (ed.getNavigator() != null) { + ed.getNavigator().updateTree(); + } + + restoreEnabledComponents(ed); + } + }); + + cancel.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + List<UUID> editorID = ConfigSciNotesManager.getOpenFilesEditorList(); + for (int i = 0; i < editorID.size(); i++) { + // Remove these files from the list of open files + if (editorID.get(i).toString().equals(uuid)) { + ConfigSciNotesManager.removeFromOpenFiles(editorID.get(i)); + break; + } + } + ed.getTabPane().remove(0); + if (ed.getTabPane().getTabCount() == 0) { + ed.addEmptyTab(); + } + restoreEnabledComponents(ed); + } + }); + + if (isWindows()) { + buttons[0] = ok; + buttons[1] = cancel; + + } else { + buttons[0] = cancel; + buttons[1] = ok; + } + + JOptionPane jop = new JOptionPane(SciNotesMessages.RESTORE_FILES_QUERY, JOptionPane.QUESTION_MESSAGE, JOptionPane.CANCEL_OPTION, null, buttons); + final JPanel panel = new JPanel(); + panel.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + c.gridheight = 1; + c.gridwidth = 1; + c.gridx = 0; + c.gridy = 0; + c.weightx = 1; + c.weighty = 0.1; + c.anchor = GridBagConstraints.PAGE_START; + c.fill = GridBagConstraints.HORIZONTAL; + panel.add(jop, c); + c.gridx = 0; + c.gridy = 1; + c.gridheight = GridBagConstraints.REMAINDER; + c.weighty = 0.9; + c.fill = GridBagConstraints.BOTH; + JScrollPane scroll = new JScrollPane(tree); + panel.add(scroll, c); + ok.requestFocusInWindow(); + + saveEnabledComponents(ed); + + return panel; + } + + /** + * @return true if the OS is Windows + */ + private static boolean isWindows() { + return System.getProperty("os.name").toLowerCase().contains("windows"); + } + + /** + * @return the files to open in the different editors + */ + private static List<File> getOpenedFiles(JTree tree, String uuid) { + List<File> list = new ArrayList(); + List<String> remove = new ArrayList(); + TreeModel model = tree.getModel(); + TreeNode node = (TreeNode) model.getChild(model.getRoot(), 0); + + for (int i = 0; i < node.getChildCount(); i++) { + DefaultMutableTreeNode mutNode = (DefaultMutableTreeNode) node.getChildAt(i); + CheckBoxNode cb = (CheckBoxNode) mutNode.getUserObject(); + if (cb.isSelected()) { + list.add(cb.getFile()); + } else { + remove.add(cb.getFile().getAbsolutePath()); + } + } + // Remove these files from the list of open files + ConfigSciNotesManager.removeFromOpenFiles(UUID.fromString(uuid), remove); + + return list; + } + + /** + * Fill the tree with the opened files + * @param uuid the editor uuid + */ + private static JTree fillTree(String uuid) { + List<UUID> editorID = ConfigSciNotesManager.getOpenFilesEditorList(); + Vector eds = new Vector(1); + + List<File> filesToOpen = removeAlreadyOpenFiles(uuid); + + if (filesToOpen.size() > 0) { + eds.add(new FilesVector("SciNotes", filesToOpen)); + } else { + return null; + } + + JTree tree = new JTree(eds); + + CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer(); + tree.setCellRenderer(renderer); + + tree.setCellEditor(new CheckBoxNodeEditor(tree)); + tree.setEditable(true); + + for (int i = 0; i < tree.getRowCount(); i++) { + tree.expandRow(i); + } + + return tree; + } + + /** + * @param editorUUID the editor UUID + * @return the files opened in the previous session minus the already opened files + */ + private static List<File> removeAlreadyOpenFiles(String editorUUID) { + List<File> filesToOpen = ConfigSciNotesManager.getOpenFilesByEditor(UUID.fromString(editorUUID)); + SciNotes editor = SciNotes.getEditorFromUUID(editorUUID); + List<File> filesToRemove = new ArrayList(); + if (editor != null) { + int n = editor.getTabPane().getTabCount(); + for (int i = 0; i < n; i++) { + ScilabEditorPane pane = editor.getTextPane(i); + String name = pane.getName(); + if (name != null) { + for (File ff : filesToOpen) { + if (ff.equals(new File(name))) { + filesToRemove.add(ff); + break; + } + } + } + } + } + + filesToOpen.removeAll(filesToRemove); + + return filesToOpen; + } + + /** + * Inner class to handle the renderer of a checkbox in a JTree + */ + static class CheckBoxNodeRenderer implements TreeCellRenderer { + + private final JCheckBox leafRenderer = new JCheckBox(); + private final DefaultTreeCellRenderer nonLeafRenderer = new DefaultTreeCellRenderer(); + + private final Color selectionBorderColor; + private final Color selectionForeground; + private final Color selectionBackground; + private final Color textForeground; + private final Color textBackground; + + private File file; + + /** + * Constructor + */ + public CheckBoxNodeRenderer() { + Font fontValue = UIManager.getFont("Tree.font"); + if (fontValue != null) { + leafRenderer.setFont(fontValue); + } + Boolean booleanValue = (Boolean) UIManager.get("Tree.drawsFocusBorderAroundIcon"); + leafRenderer.setFocusPainted(booleanValue != null && booleanValue.booleanValue()); + + selectionBorderColor = UIManager.getColor("Tree.selectionBorderColor"); + selectionForeground = UIManager.getColor("Tree.selectionForeground"); + selectionBackground = UIManager.getColor("Tree.selectionBackground"); + textForeground = UIManager.getColor("Tree.textForeground"); + textBackground = UIManager.getColor("Tree.textBackground"); + } + + /** + * {@inheritDoc} + */ + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, + boolean selected, boolean expanded, boolean leaf, int row, + boolean hasFocus) { + if (leaf) { + String stringValue = tree.convertValueToText(value, selected, expanded, leaf, row, false); + leafRenderer.setText(stringValue); + leafRenderer.setSelected(false); + + leafRenderer.setEnabled(tree.isEnabled()); + + if (selected) { + leafRenderer.setForeground(selectionForeground); + leafRenderer.setBackground(selectionBackground); + } else { + leafRenderer.setForeground(textForeground); + leafRenderer.setBackground(textBackground); + } + + if (value != null && value instanceof DefaultMutableTreeNode) { + Object obj = ((DefaultMutableTreeNode) value).getUserObject(); + if (obj instanceof CheckBoxNode) { + CheckBoxNode node = (CheckBoxNode) obj; + leafRenderer.setText(node.getText()); + leafRenderer.setSelected(node.isSelected()); + file = node.getFile(); + } + } + return leafRenderer; + } else { + return nonLeafRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + } + } + + /** + * @return the JCheckBox used to render a checkBox + */ + protected JCheckBox getLeafRenderer() { + return leafRenderer; + } + + /** + * @return the file associated with the renderer + */ + protected File getFile() { + return file; + } + } + + /** + * Inner class to handle the checkbox in a JTree + */ + static class CheckBoxNodeEditor extends AbstractCellEditor implements TreeCellEditor { + + private final CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer(); + private ChangeEvent changeEvent; + private final JTree tree; + + /** + * Default constructor + * @param tree the tree + */ + public CheckBoxNodeEditor(JTree tree) { + this.tree = tree; + } + + /** + * {@inheritDoc} + */ + @Override + public Object getCellEditorValue() { + JCheckBox checkbox = renderer.getLeafRenderer(); + CheckBoxNode checkBoxNode = new CheckBoxNode(renderer.getFile(), checkbox.getText(), checkbox.isSelected()); + return checkBoxNode; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isCellEditable(EventObject e) { + boolean ret = false; + if (e instanceof MouseEvent) { + MouseEvent mouseEvent = (MouseEvent) e; + TreePath path = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY()); + if (path != null) { + Object node = path.getLastPathComponent(); + if (node != null && node instanceof DefaultMutableTreeNode) { + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node; + ret = treeNode.isLeaf() && treeNode.getUserObject() instanceof CheckBoxNode; + } + } + } + + return ret; + } + + /** + * {@inheritDoc} + */ + @Override + public Component getTreeCellEditorComponent(JTree tree, Object value, + boolean selected, boolean expanded, boolean leaf, int row) { + Component editor = renderer.getTreeCellRendererComponent(tree, value, true, expanded, leaf, row, true); + ItemListener itemListener = new ItemListener() { + @Override + public void itemStateChanged(ItemEvent itemEvent) { + if (stopCellEditing()) { + fireEditingStopped(); + } + } + }; + if (editor instanceof JCheckBox) { + ((JCheckBox) editor).addItemListener(itemListener); + } + + return editor; + } + } + + /** + * Inner class to handle checkboxes in a tree + */ + static class CheckBoxNode { + + private String text; + private boolean selected; + private File file; + + /** + * Constructor + * @param text which will be displayed + * @param selected true if the checkbox is selected + */ + public CheckBoxNode(File f, String text, boolean selected) { + this.file = f; + this.text = text; + this.selected = selected; + } + + /** + * @return true if the checkbox is selected + */ + public boolean isSelected() { + return selected; + } + + /** + * @param newValue true if the checkbox must be selected + */ + public void setSelected(boolean newValue) { + selected = newValue; + } + + /** + * @return the String which is displayed + */ + public String getText() { + return text; + } + + /** + * @param newValue the text to set + */ + public void setText(String newValue) { + text = newValue; + } + + public File getFile() { + return file; + } + } + + /** + * Inner class to have a named Vector to add to the tree + */ + static class FilesVector extends Vector { + + private final String name; + + /** + * Constructor + * @param name the name of the List which will be display in the tree + * @param elems the elements + */ + public FilesVector(String name, List<File> elems) { + super(); + this.name = name; + for (int i = 0; i < elems.size(); i++) { + add(new CheckBoxNode(elems.get(i), elems.get(i).getName() + " (in " + elems.get(i).getParent() + ")", true)); + } + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + return name; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAction.java new file mode 100755 index 000000000..856e64592 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAction.java @@ -0,0 +1,75 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * SaveAction class + * @author Bruno JOFRET + * + */ +public final class SaveAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 1638973738114812027L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SaveAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Create Menu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SaveAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new SaveAction(tooltip, editor)); + } + + /** + * DoAction + */ + public void doAction() { + if (!getEditor().save(getEditor().getTabPane().getSelectedIndex(), true)) { + ScilabModalDialog.show(getEditor(), SciNotesMessages.COULD_NOT_SAVE_FILE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAllAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAllAction.java new file mode 100755 index 000000000..9f0837b3b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAllAction.java @@ -0,0 +1,70 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * + * @author Allan CORNET + * SaveAllAction class + */ +public final class SaveAllAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 7134703185408281234L; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SaveAllAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + int currentIndex = getEditor().getTabPane().getSelectedIndex(); + + for (int i = 0; i < getEditor().getTabPane().getTabCount(); i++) { + getEditor().getTabPane().setSelectedIndex(i); + if (!getEditor().save(getEditor().getTabPane().getSelectedIndex(), true)) { + ScilabModalDialog.show(getEditor(), SciNotesMessages.COULD_NOT_SAVE_FILE, + SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + } + getEditor().getTabPane().setSelectedIndex(currentIndex); + + } + + /** + * CreateMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SaveAllAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAndExecuteAllFilesAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAndExecuteAllFilesAction.java new file mode 100755 index 000000000..5f2220df0 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAndExecuteAllFilesAction.java @@ -0,0 +1,82 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotes; + +/** + * SaveAndExecuteAllFilesAction class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public class SaveAndExecuteAllFilesAction extends SaveAndExecuteFileAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SaveAndExecuteAllFilesAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + SciNotes editor = getEditor(); + int n = editor.getTabPane().getTabCount(); + boolean saved = true; + for (int i = 0; i < n; i++) { + ScilabEditorPane pane = editor.getTextPane(i); + if (((ScilabDocument) pane.getDocument()).isContentModified()) { + editor.getTabPane().setSelectedIndex(i); + saved = saved && editor.save(i, true); + } + } + if (saved) { + for (int i = 0; i < n; i++) { + executeFile(editor, editor.getTextPane(i).getName()); + } + } + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new SaveAndExecuteAllFilesAction(tooltip, editor)); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SaveAndExecuteAllFilesAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAndExecuteFileAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAndExecuteFileAction.java new file mode 100755 index 000000000..d27d71f6e --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAndExecuteFileAction.java @@ -0,0 +1,60 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * SaveAndExecuteFileAction Class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public class SaveAndExecuteFileAction extends ExecuteFileIntoScilabAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SaveAndExecuteFileAction(String name, SciNotes editor) { + super(name, editor); + saveBefore = true; + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new SaveAndExecuteFileAction(tooltip, editor)); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SaveAndExecuteFileAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAsAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAsAction.java new file mode 100755 index 000000000..6d2cf77a3 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveAsAction.java @@ -0,0 +1,89 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * + * @author Bruno JOFRET + * + */ +public class SaveAsAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 8327808176820789884L; + + private String path; + + /** + * Constructor + * @param name the name of the action + * @param path the default path where to open the filechooser + * @param editor SciNotes + */ + public SaveAsAction(String name, String path, SciNotes editor) { + super(name, editor); + this.path = path; + } + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SaveAsAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * DoAction + */ + public void doAction() { + if (!getEditor().saveAs(path)) { + ScilabModalDialog.show(getEditor(), SciNotesMessages.COULD_NOT_SAVE_FILE, + SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + } + + /** + * CreateMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static Object createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SaveAsAction(label, null, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + return createButton(tooltip, icon, new SaveAsAction(tooltip, null, editor)); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveFileInAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveFileInAction.java new file mode 100755 index 000000000..bfbf9a5fe --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SaveFileInAction.java @@ -0,0 +1,102 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.io.File; +import java.util.List; + +import javax.swing.KeyStroke; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.bridge.menu.SwingScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * Action to save in a predefined directory + * @author Calixte DENIZET + */ +public final class SaveFileInAction extends SaveAsAction { + + private static final long serialVersionUID = 1L; + + /** + * Constructor + * @param name the name of the action + * @param path the path where to save + * @param editor associated SciNotes instance + */ + public SaveFileInAction(String name, String path, SciNotes editor) { + super(name, path, editor); + } + + /** + * Constructor + * @param name the name of the action + * @param editor associated SciNotes instance + */ + public SaveFileInAction(String name, SciNotes editor) { + super(name, null, editor); + } + + /** + * Create a menu to add to SciNotes menu bar + * @param label label of the menu + * @param editor associated SciNotes instance + * @param key KeyStroke + * @return the menu + */ + public static Object createMenu(String label, final SciNotes editor, KeyStroke key) { + final Menu favoriteDirs = ScilabMenu.createMenu(); + ((SwingScilabMenu) favoriteDirs.getAsSimpleMenu()).addMenuListener(new MenuListener() { + + public void menuCanceled(MenuEvent e) { } + public void menuDeselected(MenuEvent e) { } + public void menuSelected(MenuEvent e) { + updateFavoriteDirsMenu(favoriteDirs, editor); + } + }); + + favoriteDirs.setText(label); + updateFavoriteDirsMenu(favoriteDirs, editor); + return favoriteDirs; + } + + /** + * Create a menu to add to SciNotes menu bar + * @param editor associated SciNotes instance + * @param path the path to open + * @return the menuitem + */ + public static MenuItem createMenu(SciNotes editor, String path) { + return createMenu(path, null, new SaveFileInAction(path, path, editor), null); + } + + /** + * Update menu displaying favorite directories. + * @param menu the menu to update + * @param editor SciNotes + */ + public static void updateFavoriteDirsMenu(Menu menu, SciNotes editor) { + ((SwingScilabMenu) menu.getAsSimpleMenu()).removeAll(); + List<File> dirs = ConfigSciNotesManager.getAllFavoriteDirs(); + + for (int i = 0; i < dirs.size(); i++) { + menu.add(createMenu(editor, dirs.get(i).getPath())); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SciNotesCompletionAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SciNotesCompletionAction.java new file mode 100755 index 000000000..83cc8ed5b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SciNotesCompletionAction.java @@ -0,0 +1,516 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.text.Element; +import javax.swing.text.StyledDocument; +import javax.swing.text.BadLocationException; + +import com.artenum.rosetta.core.CompletionItemImpl; +import com.artenum.rosetta.interfaces.core.CompletionItem; +import com.artenum.rosetta.interfaces.core.InputParsingManager; +import com.artenum.rosetta.interfaces.core.HistoryManager; +import com.artenum.rosetta.interfaces.core.GenericInterpreter; +import com.artenum.rosetta.interfaces.core.ConsoleConfiguration; +import com.artenum.rosetta.interfaces.core.CompletionManager; +import com.artenum.rosetta.interfaces.ui.CompletionWindow; +import com.artenum.rosetta.interfaces.ui.OutputView; +import com.artenum.rosetta.interfaces.ui.PromptView; +import com.artenum.rosetta.interfaces.ui.InputCommandView; + +import org.scilab.modules.completion.Completion; +import org.scilab.modules.console.CompletionAction; +import org.scilab.modules.console.SciCompletionManager; +import org.scilab.modules.console.SciInputParsingManager; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menuitem.ScilabMenuItem; +import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem; + +import org.scilab.modules.localization.Messages; + +import org.scilab.modules.scinotes.KeywordEvent; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabLexerConstants; +import org.scilab.modules.scinotes.utils.SciNotesCompletionWindow; + +/** + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class SciNotesCompletionAction extends CompletionAction { + + private SciNotes editor; + + /** + * Constructor + * @param textPane the pane associated + * @param editor SciNotes + */ + public SciNotesCompletionAction(JComponent textPane, SciNotes editor) { + this.editor = editor; + configuration = new SciNotesCompletionConfiguration(); + } + + /** + * Constructor + * @param editor SciNotes + */ + public SciNotesCompletionAction(SciNotes editor) { + this.editor = editor; + } + + /** + * Constructor + * @param name unused parameter + * @param editor SciNotes + */ + public SciNotesCompletionAction(String name, SciNotes editor) { + this.editor = editor; + } + + /** + * {@inheritDoc} + */ + public void actionPerformed(ActionEvent actionEvent) { + if (configuration == null) { + configuration = new SciNotesCompletionConfiguration(); + } + configuration.getCompletionWindow().setGraphicalContext(editor.getTextPane()); + super.actionPerformed(actionEvent); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + MenuItem menu = ScilabMenuItem.createMenuItem(); + menu.setText(label); + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).addActionListener(new ActionListener() { + private SciNotesCompletionAction action; + public void actionPerformed(ActionEvent actionEvent) { + if (action == null) { + action = new SciNotesCompletionAction(editor); + } + action.actionPerformed(actionEvent); + } + }); + + if (key != null) { + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).setAccelerator(key); + } + + return menu; + } + + /** + * Inner class to manage the completion + */ + class SciNotesInputParsingManager extends SciInputParsingManager { + + /** + * Reset + */ + public void reset() { + try { + ((ScilabDocument) editor.getTextPane().getDocument()).setFocused(true); + Element root = editor.getTextPane().getDocument().getDefaultRootElement(); + int pos = editor.getTextPane().getCaretPosition(); + int line = root.getElementIndex(pos); + int start = root.getElement(line).getStartOffset(); + editor.getTextPane().getDocument().remove(start, pos - start); + editor.getTextPane().setCaretPosition(start); + } catch (BadLocationException e) { } + } + + /** + * @return the caret position + */ + public int getCaretPosition() { + Element root = editor.getTextPane().getDocument().getDefaultRootElement(); + int pos = editor.getTextPane().getCaretPosition(); + int line = root.getElementIndex(pos); + int start = root.getElement(line).getStartOffset(); + return pos - start; + } + + /** + * @return the commandLine + */ + public String getCommandLine() { + try { + Element root = editor.getTextPane().getDocument().getDefaultRootElement(); + int pos = editor.getTextPane().getCaretPosition(); + int line = root.getElementIndex(pos); + int start = root.getElement(line).getStartOffset(); + KeywordEvent ke = editor.getTextPane().getKeywordEvent(); + if (ke.getType() == ScilabLexerConstants.FIELD) { + ke = editor.getTextPane().getKeywordEvent(ke.getStart() - 1); + if (ke.getType() == ScilabLexerConstants.ID) { + // Here we try to complete a field of an unknown variable so + // we suppose that it will be a handle + return ""; + } + } + return editor.getTextPane().getDocument().getText(start, pos - start); + } catch (BadLocationException e) { } + return ""; + } + + /** + * @param content to append + */ + public void append(String content) { + try { + ScilabDocument doc = (ScilabDocument) editor.getTextPane().getDocument(); + doc.setFocused(true); + Element root = editor.getTextPane().getDocument().getDefaultRootElement(); + int pos = editor.getTextPane().getCaretPosition(); + doc.mergeEditsBegin(); + editor.getTextPane().getDocument().insertString(pos, content, null); + doc.mergeEditsEnd(); + } catch (BadLocationException e) { } + } + + /** + * @return a Point where to put the completion window + */ + public Point getWindowCompletionLocation() { + try { + int pos = editor.getTextPane().getCaretPosition(); + Rectangle r = editor.getTextPane().modelToView(pos); + return new Point(r.x, r.y + r.height); + } catch (BadLocationException e) { } + return new Point(0, 0); + } + + /** + * @return an int + */ + public int getCompletionLevel() { + return 0; + } + + /** + * @param level an int + * @return a String to be completed + */ + public String getPartLevel(int level) { + return Completion.getPartLevel(getCommandLine()); + } + + /** + * Return an empty string to be sure that word won't be completed + * into filename. + * @param level an unused int + * @return a String + */ + public String getFilePartLevel(int level) { + return ""; + } + + /** + * @param completionResult a String + */ + public void writeCompletionPart(String completionResult) { } + + /** + * @return an int + */ + public int getNumberOfLines() { + return 0; + } + + /** + * @return a boolean + */ + public boolean isBlockEditing() { + return true; + } + + /** + * @param inputCommandView an InputCommandView + */ + public void setInputCommandView(InputCommandView inputCommandView) { } + + /** + * Put a backspace + */ + public void backspace() { + try { + Element root = editor.getTextPane().getDocument().getDefaultRootElement(); + int pos = editor.getTextPane().getCaretPosition(); + editor.getTextPane().getDocument().remove(pos - 1, 1); + editor.getTextPane().setCaretPosition(pos - 1); + } catch (BadLocationException e) { } + } + } + + /** + * Inner class to handle special completion case in SciNotes. + * When a field name is met, we can suppose that is a handle. + */ + class SciNotesCompletionManager extends SciCompletionManager { + + /** + * {@inheritDoc} + */ + public SciNotesCompletionManager() { + super(); + } + + /** + * {@inheritDoc} + */ + public List<CompletionItem> getCompletionItems() { + List<CompletionItem> list = super.getCompletionItems(); + if (list.isEmpty()) { + ScilabEditorPane sep = editor.getTextPane(); + KeywordEvent ke = sep.getKeywordEvent(); + String searchedPattern = null; + boolean handle = false; + try { + if (ke.getType() == ScilabLexerConstants.OPERATOR) { + String str = sep.getDocument().getText(ke.getStart(), ke.getLength()); + if (str.equals(".")) { + searchedPattern = " "; + } + } else if (ke.getType() == ScilabLexerConstants.FIELD) { + searchedPattern = sep.getDocument().getText(ke.getStart(), ke.getLength()); + } + } catch (BadLocationException e) { + System.err.println(e); + } + + String[] scilabHandlesDictionnary = Completion.searchHandleGraphicsPropertiesDictionary(searchedPattern); + String type = Messages.gettext("Graphics handle field"); + + list = new ArrayList<CompletionItem>(); + if (scilabHandlesDictionnary != null) { + for (String item : scilabHandlesDictionnary) { + dictionnary.add(new CompletionItemImpl(type, item + " (" + type + ")", item, Messages.gettext("No help"))); + } + } + + return dictionnary; + } + return list; + } + } + + /** + * Inner class which implements interface ConsoleConfiguration. + * Only use to be compatible with the way to complete in the console + */ + class SciNotesCompletionConfiguration implements ConsoleConfiguration { + + private SciNotesInputParsingManager xipm = new SciNotesInputParsingManager(); + private SciCompletionManager scm = new SciNotesCompletionManager(); + private SciNotesCompletionWindow cwi; + + /** + * Constructor + * @param textPane where to complete + */ + public SciNotesCompletionConfiguration() { + scm.setInputParsingManager(xipm); + cwi = new SciNotesCompletionWindow(editor, scm); + cwi.setInputParsingManager(xipm); + cwi.setGraphicalContext(editor.getTextPane()); + } + + /** + * @return an InputParsingManager + */ + public InputParsingManager getInputParsingManager() { + return xipm; + } + + /** + * Returns the current completion manager + * @return the completion manager + */ + public CompletionManager getCompletionManager() { + return scm; + } + + /** + * @return the CompletionWindow + */ + public CompletionWindow getCompletionWindow() { + return cwi; + } + + /** + * @return null + */ + public PromptView getPromptView() { + return null; + } + + /** + * @return null + */ + public OutputView getOutputView() { + return null; + } + + /** + * @return null + */ + public InputCommandView getInputCommandView() { + return null; + } + + /** + * @return null + */ + public StyledDocument getOutputViewStyledDocument() { + return null; + } + + /** + * @return null + */ + public StyledDocument getInputCommandViewStyledDocument() { + return null; + } + + /** + * @return null + */ + public HistoryManager getHistoryManager() { + return null; + } + + /** + * @return null + */ + public String getBackgroundColor() { + return null; + } + + /** + * @return null + */ + public String getForegroundColor() { + return null; + } + + /** + * @return 0 + */ + public int getScrollableUnitIncrement() { + return 0; + } + + /** + * @return 0 + */ + public int getScrollableBlockIncrement() { + return 0; + } + + /** + * @return true + */ + public boolean getHorizontalWrapAllowed() { + return true; + } + + /** + * @return true + */ + public boolean getVerticalWrapAllowed() { + return true; + } + + /** + * @return null + */ + public String getFontName() { + return null; + } + + /** + * @return 0 + */ + public int getFontStyle() { + return 0; + } + + /** + * @return 0 + */ + public int getFontSize() { + return 0; + } + + /** + * @return null + */ + public String getWelcomeLine() { + return null; + } + + /** + * @return null + */ + public GenericInterpreter getGenericInterpreter() { + return null; + } + + /** + * @return null + */ + public ActionMap getActionMapping() { + return null; + } + + /** + * @param profileName a String + */ + public void setActiveProfile(String profileName) { } + + /** + * @return null + */ + public String getActiveProfile() { + return null; + } + + /** + * @return null + */ + public InputMap getKeyMapping() { + return null; + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SearchFilesAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SearchFilesAction.java new file mode 100755 index 000000000..012e52fed --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SearchFilesAction.java @@ -0,0 +1,47 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * SearchFilesAction Class + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class SearchFilesAction extends SearchWordInFilesAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SearchFilesAction(String name, SciNotes editor) { + super(name, editor); + searchFiles = true; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SearchFilesAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SearchWordInFilesAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SearchWordInFilesAction.java new file mode 100755 index 000000000..5f0856408 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SearchWordInFilesAction.java @@ -0,0 +1,719 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.awt.event.WindowListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +import org.scilab.modules.commons.ScilabConstants; +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.bridge.filechooser.SwingScilabFileChooser; +import org.scilab.modules.gui.bridge.window.SwingScilabWindow; +import org.scilab.modules.gui.filechooser.ScilabFileChooser; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.SciNotesMessages; +import org.scilab.modules.scinotes.utils.SearchFile; + +/** + * SearchWordInFilesAction Class + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class SearchWordInFilesAction extends DefaultAction implements WindowFocusListener { + + private static final long serialVersionUID = 1L; + + private static final int GAP = 5; + private static final String FILTERNEWLINES = "filterNewlines"; + private static final String ESCAPE = "ESCAPE"; + private static final String ENABLED = "enabled"; + private static final Color ERRORCOLOR = Color.RED; + private static Color NORMALCOLOR; + + private static boolean windowAlreadyExist; + private static JFrame mainFrame; + private static Object searcher; + private static SearchWordInFilesAction current; + + private JButton buttonFind; + private JButton buttonStop; + private JButton buttonClose; + private JButton cancelButton; + private JButton chooseBaseDirButton; + private JComboBox comboBaseDir; + private JComboBox comboFilePattern; + private JComboBox comboWordPattern; + private JCheckBox checkRecursive; + private JCheckBox checkWordCase; + private JCheckBox checkFileCase; + private JCheckBox checkRegular; + private JCheckBox checkLineByLine; + private JCheckBox checkWhole; + + private boolean comboBaseDirCanceled; + private boolean comboFilePatternCanceled; + private boolean comboWordPatternCanceled; + + private String lastWordPattern; + private String lastFilePattern; + private String lastBaseDir; + + protected boolean searchFiles; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SearchWordInFilesAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + current = this; + openSearchWindow(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SearchWordInFilesAction(label, editor), key); + } + + /** + * Close the window + */ + public static void closeWindow() { + if (windowAlreadyExist) { + stopSearch(); + SwingScilabWindow window = current.getEditor().getSwingParentWindow(); + if (window != null) { + window.removeWindowFocusListener(current); + } + mainFrame.removeWindowFocusListener(current); + mainFrame.dispose(); + windowAlreadyExist = false; + } + } + + /** + * Start a search + */ + public void startSearch() { + if (SearchFile.isDone(searcher)) { + buttonStop.setEnabled(true); + buttonFind.setEnabled(false); + String baseDir = getBaseDir((String) comboBaseDir.getEditor().getItem()); + boolean recursive = checkRecursive.isSelected(); + boolean lineByLine = checkLineByLine.isSelected(); + String filePattern = (String) comboFilePattern.getEditor().getItem(); + boolean fileCase = checkFileCase.isSelected(); + String wordPattern = null; + if (!searchFiles) { + wordPattern = (String) comboWordPattern.getEditor().getItem(); + } + boolean wordCase = checkWordCase.isSelected(); + boolean wholeWord = checkWhole.isSelected(); + boolean regex = checkRegular.isSelected(); + searcher = SearchFile.getSearchResultsWindow(buttonStop, getEditor(), baseDir, recursive, !lineByLine, filePattern, fileCase, wordPattern, wordCase, wholeWord, regex); + } + } + + /** + * Stop the current search if exists + */ + public static void stopSearch() { + if (searcher != null) { + SearchFile.stopSearch(searcher); + searcher = null; + } + } + + /** + * {@inheritedDoc} + */ + @Override + public void windowGainedFocus(WindowEvent e) { + if (e.getWindow() == getEditor().getSwingParentWindow()) { + mainFrame.setAlwaysOnTop(true); + } + } + + /** + * {@inheritedDoc} + */ + @Override + public void windowLostFocus(WindowEvent e) { + if (e.getOppositeWindow() != mainFrame && e.getOppositeWindow() != getEditor().getSwingParentWindow()) { + mainFrame.setAlwaysOnTop(false); + } + } + + /** + * Open a window to get the name of the macro + * @param name the name of a macro + */ + public void openSearchWindow() { + if (windowAlreadyExist) { + mainFrame.setVisible(true); + return; + } + + mainFrame = new JFrame(); + mainFrame.setAlwaysOnTop(true); + mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + mainFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE , 0), ESCAPE); + mainFrame.getRootPane().getActionMap().put(ESCAPE, new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + closeWindow(); + } + }); + mainFrame.setTitle(SciNotesMessages.SEARCHINFILES); + mainFrame.setIconImage(new ImageIcon(FindIconHelper.findIcon("system-search", "32x32")).getImage()); + + getEditor().getSwingParentWindow().addWindowFocusListener(this); + mainFrame.addWindowFocusListener(this); + + windowAlreadyExist = true; + + JLabel baseDirLabel = new JLabel(SciNotesMessages.BASEDIRECTORY); + JLabel baseDirExpLabel = new JLabel(SciNotesMessages.BASEDIREXP); + comboBaseDir = new JComboBox(); + comboBaseDir.setEditable(true); + chooseBaseDirButton = new JButton(SciNotesMessages.CHOOSEDIR); + JPanel panelBase = new JPanel(); + JLabel filePatternLabel = new JLabel(SciNotesMessages.FILEPATTERN + ":"); + JLabel filePatternExpLabel = new JLabel(SciNotesMessages.FILEPATTERNEXP); + comboFilePattern = new JComboBox(); + comboFilePattern.setEditable(true); + ((JTextField) comboFilePattern.getEditor().getEditorComponent()).setColumns(32); + JLabel wordPatternLabel = new JLabel(SciNotesMessages.WORDPATTERN + ":"); + comboWordPattern = new JComboBox(); + comboWordPattern.setEditable(true); + comboWordPattern.getEditor().addActionListener(new ActionListener() { + + public void actionPerformed(ActionEvent e) { + updateCombos(); + startSearch(); + } + }); + ((JTextField) comboWordPattern.getEditor().getEditorComponent()).setColumns(32); + NORMALCOLOR = ((JTextField) comboWordPattern.getEditor().getEditorComponent()).getForeground(); + + JPanel panelOptions = new JPanel(); + panelOptions.setBorder(BorderFactory.createTitledBorder(SciNotesMessages.OPTIONS)); + checkWordCase = new JCheckBox(SciNotesMessages.WORDCASESENSITIVE); + checkFileCase = new JCheckBox(SciNotesMessages.FILECASESENSITIVE); + checkWhole = new JCheckBox(SciNotesMessages.WHOLE_WORD); + checkRegular = new JCheckBox(SciNotesMessages.REGULAR_EXPRESSIONS); + checkLineByLine = new JCheckBox(SciNotesMessages.FILELINEBYLINE); + checkRecursive = new JCheckBox(SciNotesMessages.RECURSIVESEARCH); + panelOptions.setLayout(new GridLayout(3, 2, GAP, GAP)); + panelOptions.add(checkWordCase); + panelOptions.add(checkFileCase); + panelOptions.add(checkWhole); + panelOptions.add(checkRegular); + panelOptions.add(checkLineByLine); + panelOptions.add(checkRecursive); + + buttonFind = new JButton(SciNotesMessages.FIND_BUTTON); + buttonStop = new JButton(SciNotesMessages.STOPBUTTON); + buttonStop.setEnabled(false); + buttonClose = new JButton(SciNotesMessages.CLOSE); + JPanel panelButton = new JPanel(); + panelButton.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); + panelButton.setLayout(new GridLayout(1, 4, GAP, GAP)); + panelButton.add(new JLabel()); + panelButton.add(buttonFind); + panelButton.add(buttonStop); + panelButton.add(buttonClose); + + restoreConfiguration(); + if (searchFiles) { + comboWordPattern.setEnabled(false); + checkWordCase.setEnabled(false); + checkWhole.setEnabled(false); + checkRegular.setEnabled(false); + checkLineByLine.setEnabled(false); + wordPatternLabel.setEnabled(false); + } + + panelBase.setLayout(new GridBagLayout()); + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = gbc.gridy = 0; + gbc.gridwidth = gbc.gridheight = 1; + gbc.weightx = gbc.weighty = 0; + gbc.anchor = GridBagConstraints.LINE_START; + panelBase.add(baseDirLabel, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.gridwidth = 3; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.BASELINE; + gbc.insets = new Insets(0, 0, GAP, 0); + panelBase.add(comboBaseDir, gbc); + + gbc.gridx = 1; + gbc.gridy = 2; + gbc.gridwidth = 2; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.EAST; + gbc.insets = new Insets(0, 0, GAP, 0); + panelBase.add(baseDirExpLabel, gbc); + + gbc.gridx = 3; + gbc.gridy = 1; + gbc.gridwidth = 1; + gbc.weightx = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.BASELINE; + panelBase.add(chooseBaseDirButton, gbc); + + gbc.gridx = 0; + gbc.gridy = 3; + gbc.anchor = GridBagConstraints.LINE_START; + panelBase.add(filePatternLabel, gbc); + + gbc.gridy = 4; + gbc.gridwidth = 3; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.BASELINE; + panelBase.add(comboFilePattern, gbc); + + gbc.gridx = 1; + gbc.gridy = 5; + gbc.gridwidth = 2; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.anchor = GridBagConstraints.EAST; + gbc.insets = new Insets(0, 0, GAP, 0); + panelBase.add(filePatternExpLabel, gbc); + + gbc.gridx = 0; + gbc.gridy = 6; + gbc.gridwidth = 1; + gbc.weightx = 0; + gbc.anchor = GridBagConstraints.LINE_START; + panelBase.add(wordPatternLabel, gbc); + + gbc.gridy = 7; + gbc.gridwidth = 3; + gbc.weightx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.BASELINE; + gbc.insets = new Insets(0, 0, GAP, 0); + panelBase.add(comboWordPattern, gbc); + + JPanel panelFrame = new JPanel(); + panelFrame.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); + panelFrame.setLayout(new BoxLayout(panelFrame, BoxLayout.PAGE_AXIS)); + panelFrame.add(panelBase); + panelFrame.add(panelOptions); + panelFrame.add(panelButton); + + mainFrame.setContentPane(panelFrame); + + mainFrame.addWindowListener(new WindowListener() { + @Override + public void windowClosed(WindowEvent arg0) { } + @Override + public void windowDeiconified(WindowEvent arg0) { } + @Override + public void windowActivated(WindowEvent arg0) { } + + @Override + public void windowClosing(WindowEvent arg0) { + closeWindow(); + } + + @Override + public void windowDeactivated(WindowEvent arg0) { } + @Override + public void windowIconified(WindowEvent arg0) { }; + @Override + public void windowOpened(WindowEvent arg0) { } + }); + + checkWordCase.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveCaseSensitive(checkWordCase.isSelected()); + } + }); + + checkFileCase.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveFileCase(checkFileCase.isSelected()); + } + }); + + checkWhole.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveWholeWord(checkWhole.isSelected()); + } + }); + + checkRecursive.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveRecursive(checkRecursive.isSelected()); + } + }); + + checkRegular.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveRegularExpression(checkRegular.isSelected()); + } + }); + + checkLineByLine.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + ConfigSciNotesManager.saveLineByLine(checkLineByLine.isSelected()); + } + }); + + chooseBaseDirButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + SwingScilabFileChooser fileChooser = ((SwingScilabFileChooser) ScilabFileChooser.createFileChooser().getAsSimpleFileChooser()); + fileChooser.setDialogTitle(SciNotesMessages.CHOOSEBASEDIR); + fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + fileChooser.setAcceptAllFileFilterUsed(false); + if (fileChooser.showOpenDialog(getEditor()) == JFileChooser.APPROVE_OPTION) { + File path = fileChooser.getSelectedFile(); + if (path == null || path.isFile()) { + path = fileChooser.getCurrentDirectory(); + } + comboBaseDir.getEditor().setItem(path.toString()); + updateFindButtonStatus(true); + } + } + }); + + buttonFind.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateCombos(); + startSearch(); + } + }); + + buttonStop.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stopSearch(); + } + + }); + + buttonStop.addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent e) { + if (mainFrame.isVisible() && e.getPropertyName().equals(SearchFile.SEARCHDONE)) { + boolean newValue = (Boolean) e.getNewValue(); + buttonFind.setEnabled(newValue); + buttonStop.setEnabled(!newValue); + } else if (e.getPropertyName().equals(ENABLED)) { + boolean newValue = (Boolean) e.getNewValue(); + comboBaseDir.setEnabled(!newValue); + comboFilePattern.setEnabled(!newValue); + chooseBaseDirButton.setEnabled(!newValue); + } + } + }); + + buttonClose.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + closeWindow(); + } + + }); + + comboBaseDir.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updateFindButtonStatus(true); + } + }); + + comboBaseDir.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + comboBaseDirCanceled = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } + }); + + comboBaseDir.getEditor().getEditorComponent().addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { } + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + if (comboBaseDirCanceled) { + comboBaseDirCanceled = false; + } else { + closeWindow(); + } + } + updateFindButtonStatus(true); + } + + @Override + public void keyPressed(KeyEvent e) { } + }); + + comboFilePattern.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + updateFindButtonStatus(false); + } + }); + + comboFilePattern.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + comboFilePatternCanceled = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } + }); + + comboFilePattern.getEditor().getEditorComponent().addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { } + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + if (comboFilePatternCanceled) { + comboFilePatternCanceled = false; + } else { + closeWindow(); + } + } + updateFindButtonStatus(false); + } + + @Override + public void keyPressed(KeyEvent e) { } + }); + + comboWordPattern.addPopupMenuListener(new PopupMenuListener() { + @Override + public void popupMenuCanceled(PopupMenuEvent e) { + comboWordPatternCanceled = true; + } + + @Override + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } + + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { } + }); + + comboWordPattern.getEditor().getEditorComponent().addKeyListener(new KeyListener() { + @Override + public void keyTyped(KeyEvent e) { } + @Override + public void keyReleased(KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { + if (comboWordPatternCanceled) { + comboWordPatternCanceled = false; + } else { + closeWindow(); + } + } + if (checkRegular.isSelected()) { + try { + Pattern.compile((String) comboWordPattern.getEditor().getItem()); + ((JTextField) comboWordPattern.getEditor().getEditorComponent()).setForeground(NORMALCOLOR); + buttonFind.setEnabled(true); + } catch (PatternSyntaxException pse) { + ((JTextField) comboWordPattern.getEditor().getEditorComponent()).setForeground(ERRORCOLOR); + buttonFind.setEnabled(false); + } + } + } + + @Override + public void keyPressed(KeyEvent e) { } + }); + + mainFrame.pack(); + mainFrame.setResizable(false); + mainFrame.setLocationRelativeTo(getEditor()); + mainFrame.setVisible(true); + } + + /** + * Update status of buttons + */ + protected void updateFindButtonStatus(boolean baseDirModified) { + String baseDir = (String) comboBaseDir.getEditor().getItem(); + String filePattern = (String) comboFilePattern.getEditor().getItem(); + boolean goodBaseDir = !baseDirModified; + if (baseDirModified && !baseDir.isEmpty()) { + baseDir = getBaseDir(baseDir); + File dir = new File(baseDir); + if (dir.exists() && dir.isDirectory()) { + goodBaseDir = true; + } + } + if (goodBaseDir) { + ((JTextField) comboBaseDir.getEditor().getEditorComponent()).setForeground(NORMALCOLOR); + buttonFind.setEnabled(!filePattern.isEmpty()); + } else { + ((JTextField) comboBaseDir.getEditor().getEditorComponent()).setForeground(ERRORCOLOR); + buttonFind.setEnabled(false); + } + } + + /** + * Replace ~ by user home + * @param baseDir the base directory + * @return correct base directory + */ + private static String getBaseDir(String baseDir) { + baseDir = baseDir.trim(); + if (baseDir != null && !baseDir.isEmpty()) { + if (baseDir.startsWith("~" + File.separator) || baseDir.equals("~")) { + return baseDir.replaceFirst("~", ScilabConstants.USERHOME); + } else if (baseDir.startsWith("SCI" + File.separator) || baseDir.equals("SCI")) { + try { + return baseDir.replaceFirst("SCI", ScilabConstants.SCI.getCanonicalPath()); + } catch (IOException e) { } + } + } + + return baseDir; + } + + /** + * Update the combos + */ + public void updateCombos() { + lastBaseDir = updateRecent(comboBaseDir, lastBaseDir, ConfigSciNotesManager.RECENTBASEDIR, ConfigSciNotesManager.BASEDIR); + lastFilePattern = updateRecent(comboFilePattern, lastFilePattern, ConfigSciNotesManager.RECENTFILEPATTERN, ConfigSciNotesManager.FILEPATTERN); + lastWordPattern = updateRecent(comboWordPattern, lastWordPattern, ConfigSciNotesManager.RECENTWORDPATTERN, ConfigSciNotesManager.WORDPATTERN); + } + + /** + * Restore configuration + */ + private void restoreConfiguration() { + checkRegular.setSelected(ConfigSciNotesManager.getRegularExpression()); + checkWhole.setSelected(ConfigSciNotesManager.getWholeWord()); + checkWordCase.setSelected(ConfigSciNotesManager.getCaseSensitive()); + checkFileCase.setSelected(ConfigSciNotesManager.getFileCase()); + checkRecursive.setSelected(ConfigSciNotesManager.getRecursive()); + checkLineByLine.setSelected(ConfigSciNotesManager.getLineByLine()); + fillCombo(comboBaseDir, ConfigSciNotesManager.RECENTBASEDIR, ConfigSciNotesManager.BASEDIR); + fillCombo(comboFilePattern, ConfigSciNotesManager.RECENTFILEPATTERN, ConfigSciNotesManager.FILEPATTERN); + fillCombo(comboWordPattern, ConfigSciNotesManager.RECENTWORDPATTERN, ConfigSciNotesManager.WORDPATTERN); + } + + /** + * fill comboBaseDir + */ + private static void fillCombo(JComboBox combo, String nodeName, String childNodeName) { + combo.removeAllItems(); + List<String> recent = ConfigSciNotesManager.getRecent(nodeName, childNodeName); + for (String item : recent) { + combo.addItem(item); + } + } + + /** + * Update recent base directory + */ + private static String updateRecent(JComboBox combo, String last, String nodeName, String childNodeName) { + String str = (String) combo.getEditor().getItem(); + if (str != null && str.length() != 0 && !str.equals(last)) { + List<String> recent = ConfigSciNotesManager.getRecent(nodeName, childNodeName); + if (!recent.contains(str)) { + combo.addItem(str); + combo.setSelectedItem(str); + ConfigSciNotesManager.saveRecent(str, nodeName, childNodeName); + last = str; + } + } + return last; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectAllAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectAllAction.java new file mode 100755 index 000000000..a369922fb --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectAllAction.java @@ -0,0 +1,59 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2009 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; +import javax.swing.text.DefaultEditorKit; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * Class to handle "select all" + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class SelectAllAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SelectAllAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ((ScilabDocument) getEditor().getTextPane().getDocument()).mergeEditsEnd(); + ((ScilabDocument) getEditor().getTextPane().getDocument()).mergeEditsBegin(); + getEditor().getTextPane().getActionMap().get(DefaultEditorKit.selectAllAction).actionPerformed(null); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SelectAllAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectBlockAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectBlockAction.java new file mode 100755 index 000000000..4d02088b8 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectBlockAction.java @@ -0,0 +1,114 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.KeywordEvent; +import org.scilab.modules.scinotes.MatchingBlockScanner; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabLexerConstants; + +/** + * Class to handle the block selection + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class SelectBlockAction extends DefaultAction { + + protected boolean isPopup; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SelectBlockAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + MatchingBlockScanner scanner = sep.getMatchingBlockManager(true).getScanner(); + KeywordEvent event = sep.getKeywordEvent(!isPopup, false); + int tok = event.getType(); + int pos; + MatchingBlockScanner.MatchingPositions mpos = null; + if (ScilabLexerConstants.isMatchable(tok)) { + pos = event.getStart(); + mpos = scanner.getMatchingBlock(pos, true); + if (mpos != null) { + sep.setSelectionStart(mpos.firstB); + sep.setSelectionEnd(mpos.secondE); + } + } + + if (mpos == null) { + scanner = sep.getMatchingBlockManager(false).getScanner(); + event = sep.getKeywordEvent(!isPopup, true); + tok = event.getType(); + if (ScilabLexerConstants.isMatchable(tok)) { + pos = event.getStart() + event.getLength(); + mpos = scanner.getMatchingBlock(pos, false); + if (mpos != null) { + sep.setSelectionStart(mpos.secondB); + sep.setSelectionEnd(mpos.firstE); + } + } + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, editor, key, new SelectBlockAction(label, editor)); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @param sba the SelectBlock action + * @return MenuItem + */ + protected static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key, final SelectBlockAction sba) { + final MenuItem menuitem = createMenu(label, null, sba, key); + ((JMenuItem) menuitem.getAsSimpleMenuItem()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + ScilabEditorPane sep = editor.getTextPane(); + boolean block = ScilabLexerConstants.isMatchable(sep.getKeywordEvent(!sba.isPopup, false).getType()); + block = block || ScilabLexerConstants.isMatchable(sep.getKeywordEvent(!sba.isPopup, true).getType()); + menuitem.setEnabled(block); + } + } + }); + + return menuitem; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectBlockInPopupAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectBlockInPopupAction.java new file mode 100755 index 000000000..0754ce67c --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SelectBlockInPopupAction.java @@ -0,0 +1,47 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * Class to handle the block selection in popup menu + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class SelectBlockInPopupAction extends SelectBlockAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SelectBlockInPopupAction(String name, SciNotes editor) { + super(name, editor); + isPopup = true; + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, editor, key, new SelectBlockInPopupAction(label, editor)); + } +}
\ No newline at end of file diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetAnchorAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetAnchorAction.java new file mode 100755 index 000000000..c86d833ea --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetAnchorAction.java @@ -0,0 +1,173 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import java.awt.Dialog.ModalityType; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.text.Element; + +import org.scilab.modules.commons.gui.FindIconHelper; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.utils.SciNotesMessages; + +/** + * SetAnchorAction Class + * @author Calixte DENIZET + */ +public class SetAnchorAction extends DefaultAction { + + private static final long serialVersionUID = 1L; + + private static final int GAP = 5; + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SetAnchorAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + openAnchorWindow(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SetAnchorAction(label, editor), key); + } + + /** + * Open a dialog to get the anchor's name + */ + public void openAnchorWindow() { + final JDialog dialog; + final JButton okButton; + final JButton cancelButton; + final JTextField textField; + + dialog = new JDialog(); + dialog.setModalityType(ModalityType.APPLICATION_MODAL); + dialog.setIconImage(new ImageIcon(FindIconHelper.findIcon("scilab")).getImage()); + JLabel label = new JLabel(SciNotesMessages.ANCHOR_NAME); + + cancelButton = new JButton(SciNotesMessages.CANCEL); + okButton = new JButton(SciNotesMessages.OK); + okButton.setPreferredSize(cancelButton.getPreferredSize()); + + JPanel panelButton = new JPanel(); + panelButton.setLayout(new GridLayout(1, 4, GAP, GAP)); + panelButton.setBorder(BorderFactory.createEmptyBorder(GAP, 0, 0, 0)); + panelButton.add(new JLabel()); + panelButton.add(new JLabel()); + panelButton.add(cancelButton); + panelButton.add(okButton); + + textField = new JTextField(); + JPanel panelText = new JPanel(); + panelText.setLayout(new GridLayout(1, 2, GAP, GAP)); + panelText.add(label); + panelText.add(textField); + + JPanel panelDialog = new JPanel(); + panelDialog.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); + panelDialog.setLayout(new BoxLayout(panelDialog, BoxLayout.PAGE_AXIS)); + panelDialog.add(panelText); + panelDialog.add(panelButton); + + dialog.setContentPane(panelDialog); + + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + dialog.dispose(); + } + }); + + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setAnchorName(textField.getText()); + dialog.dispose(); + } + }); + + textField.addKeyListener(new KeyListener() { + @Override + public void keyReleased(KeyEvent e) { + int code = e.getKeyCode(); + if (code == KeyEvent.VK_ENTER) { + okButton.doClick(); + } else if (code == KeyEvent.VK_ESCAPE) { + cancelButton.doClick(); + } + } + + @Override + public void keyPressed(KeyEvent arg0) { } + + @Override + public void keyTyped(KeyEvent arg0) { } + }); + + dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); + dialog.setTitle(SciNotesMessages.SET_ANCHOR); + dialog.pack(); + dialog.setLocationRelativeTo(getEditor()); + dialog.setVisible(true); + } + + /** + * Set the anchor's name + * @param name the anchor's name + */ + private void setAnchorName(String name) { + if (name != null && name.length() != 0) { + ScilabEditorPane sep = getEditor().getTextPane(); + sep.getXln().repaint(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + Element root = doc.getDefaultRootElement(); + ScilabDocument.ScilabLeafElement line = (ScilabDocument.ScilabLeafElement) root.getElement(root.getElementIndex(sep.getCaretPosition())); + line.setAnchor(name); + getEditor().getNavigator().update(); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetColorsAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetColorsAction.java new file mode 100755 index 000000000..229f82911 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetColorsAction.java @@ -0,0 +1,54 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.commons.ScilabGeneralPrefs; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * SetColorsAction Class + * @author Calixte DENIZET + */ +public class SetColorsAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SetColorsAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + ScilabGeneralPrefs.openPreferences("colors/"); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SetColorsAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetFontAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetFontAction.java new file mode 100755 index 000000000..5c71f96e1 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SetFontAction.java @@ -0,0 +1,54 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2012 - Scilab Enterprises - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.commons.ScilabGeneralPrefs; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * SetFontAction Class + * @author Calixte DENIZET + */ +public class SetFontAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public SetFontAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + @Override + public void doAction() { + ScilabGeneralPrefs.openPreferences("fonts/"); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key Keystroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, final SciNotes editor, KeyStroke key) { + return createMenu(label, null, new SetFontAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SplitAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SplitAction.java new file mode 100755 index 000000000..acf230fb7 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/SplitAction.java @@ -0,0 +1,141 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +package org.scilab.modules.scinotes.actions; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.StringTokenizer; + +import javax.swing.ButtonGroup; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JSplitPane; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.EditorComponent; + +/** + * SplitAction Class + * @author Calixte DENIZET + */ +public final class SplitAction extends DefaultAction { + + /** + * serialVersionUID + */ + private static final long serialVersionUID = 1L; + + private int state; + + /** + * Construtor + * @param name the name of the action + * @param editor SciNotes + */ + public SplitAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + switch (state) { + case 0 : + getEditor().removeSplit(); + return; + case 1 : + getEditor().splitTab(false); + return; + default : + getEditor().splitTab(true); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return createMenu + */ + public static Menu createMenu(String label, final SciNotes editor, KeyStroke key) { + StringTokenizer tokens = new StringTokenizer(label, ";\uff1b"); + String labelSplitView = tokens.nextToken(); + String labelOff = tokens.nextToken(); + String labelH = tokens.nextToken(); + String labelV = tokens.nextToken(); + + SplitAction ln = new SplitAction(labelSplitView, editor); + Menu menu = ScilabMenu.createMenu(); + menu.setText(labelSplitView); + + ButtonGroup group = new ButtonGroup(); + JRadioButtonMenuItem radio; + final JRadioButtonMenuItem[] arr = new JRadioButtonMenuItem[3]; + String[] labels = new String[] {labelOff, labelH, labelV}; + + for (int i = 0; i < 3; i++) { + radio = createRadioButtonMenuItem(ln, labels[i], i); + group.add(radio); + ((JMenu) menu.getAsSimpleMenu()).add(radio); + arr[i] = radio; + } + + arr[0].setSelected(true); + + ((JMenu) menu.getAsSimpleMenu()).addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + EditorComponent c = editor.getTextPane().getEditorComponent(); + int state = 0; + if (c.isSplited()) { + JSplitPane split = c.getSplitPane(); + if (split.getOrientation() == JSplitPane.HORIZONTAL_SPLIT) { + state = 1; + } else { + state = 2; + } + } + arr[state].setSelected(true); + } + } + }); + + return menu; + } + + /** + * createRadioButtonMenuItem + * @param split the SplitAction + * @param title the label of the menuitem + * @param state the state associated with the menuitem + * @return JRadioButtonMenuItem + */ + private static JRadioButtonMenuItem createRadioButtonMenuItem(final SplitAction split, String title, final int state) { + JRadioButtonMenuItem radio = new JRadioButtonMenuItem(title); + radio.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + split.state = state; + split.doAction(); + } + }); + + return radio; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/TabifyAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/TabifyAction.java new file mode 100755 index 000000000..f77b67da4 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/TabifyAction.java @@ -0,0 +1,97 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotesCaret; +import org.scilab.modules.scinotes.TabManager; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * Class Tabify action for SciNotes + * @author Sylvestre Koumar + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class TabifyAction extends DefaultAction { + + /** + * Default constructor + * @param name the name of the action + * @param editor the editor + */ + public TabifyAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Function doAction + */ + public synchronized void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + int posC = sep.getCaretPosition(); + TabManager tab = sep.getTabManager(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + + doc.mergeEditsBegin(); + if (((SciNotesCaret) sep.getCaret()).isEmptySelection()) { + if (start == end) { + tab.insertTab(start); + } else { + int[] ret = tab.tabifyLines(start, end - 1); + if (ret != null) { + if (posC == start) { + sep.select(ret[1], ret[0]); + } else { + sep.select(ret[0], ret[1]); + } + } + } + } else { + int[][] pos = ((SciNotesCaret) sep.getCaret()).getSelectedPositions(); + ((SciNotesCaret) sep.getCaret()).protectHighlights(true); + int ret; + int sret = 0; + for (int i = 0; i < pos.length; i++) { + if (pos[i][0] < pos[i][1]) { + ret = tab.insertTab(pos[i][0] + sret); + sret += ret; + pos[i][0] += sret; + pos[i][1] += sret; + } + } + ((SciNotesCaret) sep.getCaret()).protectHighlights(false); + ((SciNotesCaret) sep.getCaret()).updateHighlights(); + } + doc.mergeEditsEnd(); + } + + /** + * Create the MenuItem for tabify action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new TabifyAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ToLowerCaseAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ToLowerCaseAction.java new file mode 100755 index 000000000..64c4a266a --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ToLowerCaseAction.java @@ -0,0 +1,67 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * ToLowerCaseAction Class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class ToLowerCaseAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ToLowerCaseAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + String str = sep.getSelectedText(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + + if (str != null) { + doc.mergeEditsBegin(); + sep.replaceSelection(str.toLowerCase()); + sep.select(start, end); + doc.mergeEditsEnd(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new ToLowerCaseAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ToUpperCaseAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ToUpperCaseAction.java new file mode 100755 index 000000000..ad7f89199 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/ToUpperCaseAction.java @@ -0,0 +1,67 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * ToUpperCaseAction Class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class ToUpperCaseAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public ToUpperCaseAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + String str = sep.getSelectedText(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + + if (str != null) { + doc.mergeEditsBegin(); + sep.replaceSelection(str.toUpperCase()); + sep.select(start, end); + doc.mergeEditsEnd(); + } + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new ToUpperCaseAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UnCommentAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UnCommentAction.java new file mode 100755 index 000000000..9e68dd4f8 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UnCommentAction.java @@ -0,0 +1,79 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.CommentManager; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * UnCommentAction Class + * @author Calixte DENIZET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class UnCommentAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public UnCommentAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + int pos = sep.getCaretPosition(); + CommentManager com = sep.getCommentManager(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + int[] ret; + + doc.mergeEditsBegin(); + if (start == end) { + ret = com.uncommentLines(start, start); + sep.setCaretPosition(ret[0]); + } else { + ret = com.uncommentLines(start, end); + if (ret != null) { + if (pos == start) { + sep.select(ret[1], ret[0]); + } else { + sep.select(ret[0], ret[1]); + } + } + } + doc.mergeEditsEnd(); + } + + /** + * createMenu + * @param label label of the menu + * @param editor SciNotes + * @param key KeyStroke + * @return MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new UnCommentAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UnTabifyAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UnTabifyAction.java new file mode 100755 index 000000000..f7f11b836 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UnTabifyAction.java @@ -0,0 +1,96 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotesCaret; +import org.scilab.modules.scinotes.TabManager; +import org.scilab.modules.scinotes.ScilabDocument; + +/** + * Class Untabify action for SciNotes + * @author Sylvestre Koumar + * + */ +@SuppressWarnings(value = { "serial" }) +public class UnTabifyAction extends DefaultAction { + + /** + * Default constructor + * @param name the name of the action + * @param editor the editor + */ + public UnTabifyAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * Function doAction + */ + public void doAction() { + ScilabEditorPane sep = getEditor().getTextPane(); + int start = sep.getSelectionStart(); + int end = sep.getSelectionEnd(); + int posC = sep.getCaretPosition(); + TabManager tab = sep.getTabManager(); + ScilabDocument doc = (ScilabDocument) sep.getDocument(); + + doc.mergeEditsBegin(); + if (((SciNotesCaret) sep.getCaret()).isEmptySelection()) { + if (start == end) { + tab.untabifyLine(start); + } else { + int[] ret = tab.untabifyLines(start, end - 1); + if (ret != null) { + if (posC == start) { + sep.select(ret[1], ret[0]); + } else { + sep.select(ret[0], ret[1]); + } + } + } + } else { + int[][] pos = ((SciNotesCaret) sep.getCaret()).getSelectedPositions(); + ((SciNotesCaret) sep.getCaret()).protectHighlights(true); + int ret; + int sret = 0; + for (int i = 0; i < pos.length; i++) { + if (pos[i][0] < pos[i][1]) { + ret = tab.removeTab(pos[i][0] - sret); + sret += ret; + pos[i][0] -= sret; + pos[i][1] -= sret; + } + } + ((SciNotesCaret) sep.getCaret()).protectHighlights(false); + ((SciNotesCaret) sep.getCaret()).updateHighlights(); + } + + doc.mergeEditsEnd(); + } + + /** + * Create the MenuItem for untabify action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new UnTabifyAction(label, editor), key); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UndoAction.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UndoAction.java new file mode 100755 index 000000000..9ed6d97c2 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/actions/UndoAction.java @@ -0,0 +1,68 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.actions; + +import javax.swing.JButton; +import javax.swing.KeyStroke; + +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.scinotes.SciNotes; + +/** + * CommentAction Class + * @author Bruno JOFRET + * + */ +@SuppressWarnings(value = { "serial" }) +public final class UndoAction extends DefaultAction { + + /** + * Constructor + * @param name the name of the action + * @param editor SciNotes + */ + public UndoAction(String name, SciNotes editor) { + super(name, editor); + } + + /** + * doAction + */ + public void doAction() { + getEditor().undo(); + } + + /** + * Create the MenuItem for undo action + * @param label label of the menu + * @param editor Editor + * @param key KeyStroke + * @return a MenuItem + */ + public static MenuItem createMenu(String label, SciNotes editor, KeyStroke key) { + return createMenu(label, null, new UndoAction(label, editor), key); + } + + /** + * createButton + * @param tooltip the tooltip + * @param icon an icon name searched in SCI/modules/gui/images/icons/ + * @param editor SciNotes + * @return PushButton + */ + public static JButton createButton(String tooltip, String icon, SciNotes editor) { + JButton button = createButton(tooltip, icon, new UndoAction(tooltip, editor)); + editor.setUndoButton(button); + return button; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/style/FilterManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/style/FilterManager.java new file mode 100755 index 000000000..4ab635514 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/style/FilterManager.java @@ -0,0 +1,9 @@ +package org.scilab.modules.scinotes.style; + +import org.scilab.modules.scinotes.ScilabDocument; + +public class FilterManager { + + public FilterManager(final ScilabDocument scilabDocument) { + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/CodeNavigatorTab.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/CodeNavigatorTab.java new file mode 100755 index 000000000..dd838f8b0 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/CodeNavigatorTab.java @@ -0,0 +1,86 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.tabfactory; + +import java.util.List; +import java.util.ListIterator; + +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; +import org.scilab.modules.gui.utils.ClosingOperationsManager; +import org.scilab.modules.gui.utils.WindowsConfigurationManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.NavigatorWindow; + +/** + * Class to create SciNotes instances + * + * @author Calixte DENIZET + */ +public class CodeNavigatorTab { + + /** + * @param uuid + * the uuid to restore + * @return a new SciNotes instance + */ + public static NavigatorWindow getCodeNavigatorInstance( + final SciNotes editor, String uuid) { + final NavigatorWindow nav; + if (uuid != null) { + nav = new NavigatorWindow(editor, uuid); + } else { + nav = new NavigatorWindow(editor); + ScilabTabFactory.getInstance().addToCache(nav); + } + + ClosingOperationsManager.registerClosingOperation((SwingScilabDockablePanel) nav, + new ClosingOperationsManager.ClosingOperation() { + + @Override + public int canClose() { + return 1; + } + + @Override + public void destroy() { + nav.closeNavigator(); + } + + @Override + public String askForClosing(final List<SwingScilabDockablePanel> list) { + return null; + } + + @Override + public void updateDependencies(List<SwingScilabDockablePanel> list, + ListIterator<SwingScilabDockablePanel> it) { + } + }); + + WindowsConfigurationManager.registerEndedRestoration( + (SwingScilabDockablePanel) nav, + new WindowsConfigurationManager.EndedRestoration() { + + @Override + public void finish() { + nav.changeToolBar(); + } + }); + + ClosingOperationsManager.addDependency((SwingScilabDockablePanel) editor, + (SwingScilabDockablePanel) nav); + + return nav; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/CodeNavigatorTabFactory.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/CodeNavigatorTabFactory.java new file mode 100755 index 000000000..d65e3e58b --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/CodeNavigatorTabFactory.java @@ -0,0 +1,92 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.tabfactory; + +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; + +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.NavigatorWindow; + +/** + * The main Tab factory. + * A component which needs to restore a Tab with a given uuid must register its factory. + * + * @author Calixte DENIZET + */ +public class CodeNavigatorTabFactory extends AbstractScilabTabFactory { + + public static final String APPLICATION = "CodeNavigator"; + public static final String PACKAGE = "SciNotes"; + public static final String CLASS = "org.scilab.modules.scinotes.tabfactory.CodeNavigatorTabFactory"; + + private static CodeNavigatorTabFactory instance; + + /** + * Default constructor + */ + public CodeNavigatorTabFactory() { + if (instance == null) { + instance = this; + } + } + + /** + * {@inheritDoc} + */ + public SwingScilabDockablePanel getTab(String uuid) { + String editorUUID = ConfigSciNotesManager.getCodeNavigatorState(uuid); + SciNotes editor = (SciNotes) ScilabTabFactory.getInstance().getFromCache(editorUUID); + + return CodeNavigatorTab.getCodeNavigatorInstance(editor, uuid); + } + + /** + * {@inheritDoc} + */ + public String getPackage() { + return PACKAGE; + } + + /** + * {@inheritDoc} + */ + public String getClassName() { + return CLASS; + } + + /** + * {@inheritDoc} + */ + public String getApplication() { + return APPLICATION; + } + + /** + * {@inheritDoc} + */ + public boolean isAValidUUID(String uuid) { + return ConfigSciNotesManager.getCodeNavigatorState(uuid) != null; + } + + /** + * @return an instance of this factory + */ + public static CodeNavigatorTabFactory getInstance() { + new CodeNavigatorTabFactory(); + + return instance; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SciNotesTab.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SciNotesTab.java new file mode 100755 index 000000000..42c37a2ad --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SciNotesTab.java @@ -0,0 +1,88 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.tabfactory; + +import java.util.List; +import java.util.ListIterator; + +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; +import org.scilab.modules.gui.utils.ClosingOperationsManager; +import org.scilab.modules.gui.utils.WindowsConfigurationManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesGUI; + +/** + * Class to create SciNotes instances + * + * @author Calixte DENIZET + */ +public class SciNotesTab { + + /** + * @param uuid + * the uuid to restore + * @return a new SciNotes instance + */ + public static SciNotes getEditorInstance(String uuid) { + SciNotes editorInstance; + if (uuid != null) { + editorInstance = new SciNotes(uuid); + } else { + editorInstance = new SciNotes(); + ScilabTabFactory.getInstance().addToCache(editorInstance); + } + SciNotesGUI.init(editorInstance); + + final SciNotes ed = editorInstance; + ClosingOperationsManager.registerClosingOperation( + (SwingScilabDockablePanel) editorInstance, + new ClosingOperationsManager.ClosingOperation() { + + @Override + public int canClose() { + return ed.canClose() ? 1 : 0; + } + + @Override + public void destroy() { + ed.closeSciNotes(); + } + + @Override + public String askForClosing(final List<SwingScilabDockablePanel> list) { + return ed.askForClosing(); + } + + @Override + public void updateDependencies(List<SwingScilabDockablePanel> list, + ListIterator<SwingScilabDockablePanel> it) { + } + }); + + WindowsConfigurationManager.registerEndedRestoration( + (SwingScilabDockablePanel) editorInstance, + new WindowsConfigurationManager.EndedRestoration() { + + @Override + public void finish() { + ed.endedRestoration(); + } + }); + + ClosingOperationsManager + .addDependencyWithRoot((SwingScilabDockablePanel) editorInstance); + + return editorInstance; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SciNotesTabFactory.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SciNotesTabFactory.java new file mode 100755 index 000000000..cf5cef588 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SciNotesTabFactory.java @@ -0,0 +1,90 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.tabfactory; + +import java.util.List; +import java.util.UUID; + +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory; + +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; + +/** + * The main Tab factory. + * A component which needs to restore a Tab with a given uuid must register its factory. + * + * @author Calixte DENIZET + */ +public class SciNotesTabFactory extends AbstractScilabTabFactory { + + public static final String APPLICATION = "SciNotes"; + public static final String PACKAGE = "SciNotes"; + public static final String CLASS = "org.scilab.modules.scinotes.tabfactory.SciNotesTabFactory"; + + private static SciNotesTabFactory instance; + + /** + * Default constructor + */ + public SciNotesTabFactory() { + if (instance == null) { + instance = this; + } + } + + /** + * {@inheritDoc} + */ + public SwingScilabDockablePanel getTab(String uuid) { + return SciNotesTab.getEditorInstance(uuid); + } + + /** + * {@inheritDoc} + */ + public String getPackage() { + return PACKAGE; + } + + /** + * {@inheritDoc} + */ + public String getClassName() { + return CLASS; + } + + /** + * {@inheritDoc} + */ + public String getApplication() { + return APPLICATION; + } + + /** + * {@inheritDoc} + */ + public boolean isAValidUUID(String uuid) { + return ConfigSciNotesManager.getEditorsUUID().contains(uuid); + } + + /** + * @return an instance of this factory + */ + public static SciNotesTabFactory getInstance() { + new SciNotesTabFactory(); + + return instance; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SearchInFilesTab.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SearchInFilesTab.java new file mode 100755 index 000000000..8fa997701 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SearchInFilesTab.java @@ -0,0 +1,86 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.tabfactory; + +import java.util.List; +import java.util.ListIterator; + +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; +import org.scilab.modules.gui.utils.ClosingOperationsManager; +import org.scilab.modules.gui.utils.WindowsConfigurationManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.SearchFile; + +/** + * Class to create SciNotes instances + * + * @author Calixte DENIZET + */ +public class SearchInFilesTab { + + /** + * @param uuid + * the uuid to restore + * @return a new SciNotes instance + */ + public static SearchFile getSearchInFilesTabInstance(final SciNotes editor, + String uuid) { + final SearchFile sf; + if (uuid != null) { + sf = new SearchFile(editor, uuid); + } else { + sf = new SearchFile(editor); + ScilabTabFactory.getInstance().addToCache(sf); + } + + ClosingOperationsManager.registerClosingOperation((SwingScilabDockablePanel) sf, + new ClosingOperationsManager.ClosingOperation() { + + @Override + public int canClose() { + return 1; + } + + @Override + public void destroy() { + sf.closeSearchInFiles(); + } + + @Override + public String askForClosing(final List<SwingScilabDockablePanel> list) { + return null; + } + + @Override + public void updateDependencies(List<SwingScilabDockablePanel> list, + ListIterator<SwingScilabDockablePanel> it) { + } + }); + + WindowsConfigurationManager.registerEndedRestoration( + (SwingScilabDockablePanel) sf, + new WindowsConfigurationManager.EndedRestoration() { + + @Override + public void finish() { + sf.changeToolBar(); + } + }); + + ClosingOperationsManager.addDependency((SwingScilabDockablePanel) editor, + (SwingScilabDockablePanel) sf); + + return sf; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SearchInFilesTabFactory.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SearchInFilesTabFactory.java new file mode 100755 index 000000000..867f143d5 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/tabfactory/SearchInFilesTabFactory.java @@ -0,0 +1,92 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.tabfactory; + +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.tabfactory.AbstractScilabTabFactory; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; + +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.utils.ConfigSciNotesManager; +import org.scilab.modules.scinotes.utils.NavigatorWindow; + +/** + * The main Tab factory. + * A component which needs to restore a Tab with a given uuid must register its factory. + * + * @author Calixte DENIZET + */ +public class SearchInFilesTabFactory extends AbstractScilabTabFactory { + + public static final String APPLICATION = "SearchInFiles"; + public static final String PACKAGE = "SciNotes"; + public static final String CLASS = "org.scilab.modules.scinotes.tabfactory.SearchInFilesTabFactory"; + + private static SearchInFilesTabFactory instance; + + /** + * Default constructor + */ + public SearchInFilesTabFactory() { + if (instance == null) { + instance = this; + } + } + + /** + * {@inheritDoc} + */ + public SwingScilabDockablePanel getTab(String uuid) { + String editorUUID = ConfigSciNotesManager.getSearchInFilesState(uuid); + SciNotes editor = (SciNotes) ScilabTabFactory.getInstance().getFromCache(editorUUID); + + return SearchInFilesTab.getSearchInFilesTabInstance(editor, uuid); + } + + /** + * {@inheritDoc} + */ + public String getPackage() { + return PACKAGE; + } + + /** + * {@inheritDoc} + */ + public String getClassName() { + return CLASS; + } + + /** + * {@inheritDoc} + */ + public String getApplication() { + return APPLICATION; + } + + /** + * {@inheritDoc} + */ + public boolean isAValidUUID(String uuid) { + return ConfigSciNotesManager.getSearchInFilesState(uuid) != null; + } + + /** + * @return an instance of this factory + */ + public static SearchInFilesTabFactory getInstance() { + new SearchInFilesTabFactory(); + + return instance; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/CodeExporter.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/CodeExporter.java new file mode 100755 index 000000000..bf8afd366 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/CodeExporter.java @@ -0,0 +1,158 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.StringReader; + +import java.awt.print.PageFormat; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.stream.StreamSource; + +import org.scilab.modules.commons.ScilabConstants; +import org.scilab.modules.commons.xml.ScilabTransformerFactory; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.helptools.scilab.AbstractScilabCodeHandler; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; + +import org.apache.fop.apps.FopFactory; +import org.apache.fop.apps.Fop; +import org.apache.fop.apps.FOUserAgent; +import org.apache.fop.apps.MimeConstants; + +/** + * Code converter Class + * @author Calixte DENIZET + */ +public class CodeExporter extends FOCodeConverter { + + /** + * Constant for PDF + */ + public static final String PDF = MimeConstants.MIME_PDF; + + /** + * Constant for PS + */ + public static final String PS = MimeConstants.MIME_POSTSCRIPT; + + /** + * Constant for EPS + */ + public static final String EPS = MimeConstants.MIME_EPS; + + /** + * Constant for RTF + */ + public static final String RTF = MimeConstants.MIME_RTF; + + /** + * Constant for PNG + */ + public static final String PNG = MimeConstants.MIME_PNG; + + /** + * Constant for PREVIEW a document in AWT window + */ + public static final String PREVIEW = MimeConstants.MIME_FOP_AWT_PREVIEW; + + /** + * Constant for PRINT + */ + public static final String PRINT = MimeConstants.MIME_FOP_PRINT; + + private static final String CREATOR = "SciNotes for Scilab"; + private SciNotes editor; + + /** + * Constructor + * @param pane the ScilabEditorPane where the code must be converted. + */ + public CodeExporter(ScilabEditorPane pane) { + super(pane); + editor = pane.getEditor(); + } + + /** + * Make the conversion of a ScilabEditorPane + * @param pane the ScilabEditorPane + * @param the fileName for the output + * @param type must on of the constants PDF, EPS, ... + * @param format the page format + */ + public static void convert(ScilabEditorPane pane, String fileName, String type, PageFormat format) { + CodeExporter exporter = new CodeExporter(pane); + exporter.convert(((ScilabDocument) pane.getDocument()).getText(), pane.getXln().getLineNumber(), fileName, type, pane.getShortName(), format); + } + + /** + * Make the conversion of a ScilabEditorPane + * @param pane the ScilabEditorPane + * @param lineNumberArray an array containing integers to number the lines + * @param the fileName for the output + * @param type must on of the constants PDF, EPS, ... + * @param format the page format + */ + public void convert(String code, int[] lineNumberArray, String fileName, String type, String title, PageFormat format) { + FopFactory fopFactory = FopFactory.newInstance(); + OutputStream out = null; + + try { + fopFactory.setUserConfig(new File(ScilabConstants.SCI + "/modules/helptools/etc/fopconf.xml")); + FOUserAgent userAgent = fopFactory.newFOUserAgent(); + userAgent.setProducer(CREATOR); + userAgent.setTitle(title); + userAgent.setAuthor(System.getProperty("user.name")); + Fop fop; + if (!type.equals(PRINT) && !type.equals(PREVIEW) && fileName != null && !fileName.isEmpty()) { + out = new BufferedOutputStream(new FileOutputStream(new File(fileName))); + fop = fopFactory.newFop(type, userAgent, out); + } else { + fop = fopFactory.newFop(type, userAgent); + } + String factoryName = ScilabTransformerFactory.useDefaultTransformerFactoryImpl(); + TransformerFactory factory = TransformerFactory.newInstance(); + Transformer transformer = factory.newTransformer(); + String str = super.convert(code, lineNumberArray, format); + Source src = new StreamSource(new StringReader(str)); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(src, res); + ScilabTransformerFactory.restoreTransformerFactoryImpl(factoryName); + } catch (Exception e) { + if (type.equals(PRINT)) { + ScilabModalDialog.show(editor, SciNotesMessages.PRINTERERROR + "\n" + e.getLocalizedMessage()); + } else { + System.err.println(SciNotesMessages.EXPORTERROR + ":"); + e.printStackTrace(); + } + } finally { + try { + if (out != null) { + out.close(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ConfigSciNotesManager.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ConfigSciNotesManager.java new file mode 100755 index 000000000..02aefcc24 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ConfigSciNotesManager.java @@ -0,0 +1,1558 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2009 - INRIA - Allan SIMON + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Toolkit; +import java.awt.print.Paper; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Hashtable; +import java.util.Properties; +import java.util.Enumeration; +import java.util.Map; +import java.util.UUID; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.scilab.modules.commons.ScilabCommons; +import org.scilab.modules.commons.ScilabConstants; +import org.scilab.modules.commons.ScilabCommonsUtils; +import org.scilab.modules.commons.xml.ScilabXMLUtilities; +import org.scilab.modules.commons.xml.ScilabDocumentBuilderFactory; +import org.scilab.modules.commons.xml.ScilabTransformerFactory; +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.gui.utils.Position; +import org.scilab.modules.gui.utils.Size; + +import org.scilab.modules.scinotes.ScilabView; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.TabManager; +import org.scilab.modules.scinotes.MatchingBlockManager; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Text; +import org.xml.sax.SAXException; + +/** + * Configuration class which interacts with the file etc/scinotesConfiguration.xml + */ +public final class ConfigSciNotesManager { + + public static final String RECENTBASEDIR = "recentBaseDir"; + public static final String BASEDIR = "baseDir"; + public static final String RECENTFILEPATTERN = "recentFilePattern"; + public static final String FILEPATTERN = "filePattern"; + public static final String RECENTWORDPATTERN = "recentWordPattern"; + public static final String WORDPATTERN = "wordPattern"; + + private static final int BUFSIZE = 1024; + + private static final int MARGIN = 20; + + private static final String ERROR_READ = "Could not load file: "; + private static final String ERROR_WRITE = "Could not save file: "; + private static final String VALUE = "value"; + private static final String VERSION = "version"; + private static final String STYLE = "style"; + private static final String DEFAULT = "default"; + private static final String WIDTH = "width"; + private static final String HEIGHT = "height"; + private static final String EDITOR = "SciNotes"; + + private static final String FOREGROUNDCOLOR = "ForegroundColor"; + private static final String BACKGROUNDCOLOR = "BackgroundColor"; + private static final String ALTERNCOLORS = "AlternColors"; + private static final String COLOR1 = "color1"; + private static final String COLOR2 = "color2"; + private static final String LINECOLOR = "linecolor"; + private static final String CONTOURCOLOR = "contourcolor"; + private static final String COLORPREFIX = "#"; + + private static final String NAME = "name"; + private static final String NULL = "null"; + + private static final String PROFILE = "Profile"; + + private static final String RECENT_SEARCH = "recentSearch"; + private static final String SEARCH = "search"; + private static final String RECENT_REPLACE = "recentReplace"; + private static final String REPLACE = "replace"; + private static final String RECURSIVE = "recursiveSearch"; + private static final String LINEBYLINE = "readLineByLine"; + private static final String FILECASE = "fileCase"; + private static final String SEARCHINFILES = "searchInFiles"; + + private static final String EXPRESSION = "exp"; + private static final String REGULAR_EXPRESION = "regularExp"; + private static final String CIRCULAR = "circularSearch"; + private static final String WORD_WARP = "wordWarp"; + private static final String WHOLE_WORD = "wholeWord"; + private static final String CASE_SENSITIVE = "caseSensitive"; + private static final String STATE_FLAG = "state"; + + private static final String SETTING = "Setting"; + private static final String SCINOTES = "scinotes"; + private static final String TRUE = "true"; + private static final String FALSE = "false"; + private static final String DOCUMENT = "document"; + private static final String PATH = "path"; + private static final String RECENT_FILES = "recentFiles"; + private static final String OPEN_FILES = "openFiles"; + private static final String RESTOREFILES = "RestoreFiles"; + private static final String EDITORINST = "editorInstance"; + private static final String EDITORUUID = "EditorUUID"; + private static final String PANEINST = "paneInstance"; + private static final String PANEINST_EX = "paneInstanceExtra"; + + private static final String FAVORITE_DIRS = "favoriteDirectories"; + private static final String DIRECTORY = "Directory"; + + private static final String PAPER = "PaperFormat"; + private static final String MARGINLEFT = "MarginLeft"; + private static final String MARGINRIGHT = "MarginRight"; + private static final String MARGINTOP = "MarginTop"; + private static final String MARGINBOTTOM = "MarginBottom"; + + private static final String CODENAVIGATOR = "CodeNavigator"; + + private static final String SCI = "SCI"; + private static final String SCINOTES_CONFIG_FILE = System.getenv(SCI) + "/modules/scinotes/etc/scinotesConfiguration.xml"; + + private static final int MAXRECENT = 20; + + private static Document document; + + private static boolean updated; + private static boolean mustSave = true; + + private static String USER_SCINOTES_CONFIG_FILE = ScilabConstants.SCIHOME.toString() + "/scinotesConfiguration.xml"; + + static { + if (ScilabConstants.SCIHOME != null && ScilabConstants.SCIHOME.canRead() && ScilabConstants.SCIHOME.canWrite()) { + USER_SCINOTES_CONFIG_FILE = ScilabConstants.SCIHOME.toString() + "/scinotesConfiguration.xml"; + } else { + USER_SCINOTES_CONFIG_FILE = SCINOTES_CONFIG_FILE; + mustSave = false; + } + } + + /** + * Constructor + */ + private ConfigSciNotesManager() { + throw new UnsupportedOperationException(); + } + + /** + * Create a copy of Scilab configuration file in the user directory + */ + public static void createUserCopy() { + if (checkVersion() && mustSave) { + /* Create a local copy of the configuration file */ + ScilabCommonsUtils.copyFile(new File(SCINOTES_CONFIG_FILE), new File(USER_SCINOTES_CONFIG_FILE)); + document = null; + updated = true; + } + } + + /** + * Get the name of the user configuration file + * @return the name of the configuration file + */ + public static String getUserConfigFile() { + return USER_SCINOTES_CONFIG_FILE; + } + + /** + * @return true if scinotesConfiguration.xml in etc has a version greater than the version in home + */ + public static boolean checkVersion() { + if (updated) { + return false; + } + + File fileConfig = new File(USER_SCINOTES_CONFIG_FILE); + + if (fileConfig.exists()) { + document = null; + readDocument(SCINOTES_CONFIG_FILE); + Node setting = getNodeChild(null, SETTING); + String str = ((Element) setting).getAttribute(VERSION); + if (str != null && str.length() != 0) { + float versionEtc = Float.parseFloat(str); + document = null; + readDocument(); + setting = getNodeChild(null, SETTING); + str = ((Element) setting).getAttribute(VERSION); + document = null; + + if (str != null && str.length() != 0) { + float versionHome = Float.parseFloat(str); + return versionEtc != versionHome; + } + } + } + + return true; + } + + /** + * @return the paper format saved in previous session + */ + public static Paper getPaperFormat() { + readDocument(); + + Element root = document.getDocumentElement(); + + NodeList profiles = root.getElementsByTagName(PROFILE); + Element scinotesProfile = (Element) profiles.item(0); + + NodeList allSizeElements = scinotesProfile.getElementsByTagName(PAPER); + Element paper = (Element) allSizeElements.item(0); + + if (paper == null) { + return new Paper(); + } + + Paper p = new Paper(); + double width = Double.parseDouble(paper.getAttribute(WIDTH)); + double height = Double.parseDouble(paper.getAttribute(HEIGHT)); + double marginLeft = Double.parseDouble(paper.getAttribute(MARGINLEFT)); + double marginRight = Double.parseDouble(paper.getAttribute(MARGINRIGHT)); + double marginTop = Double.parseDouble(paper.getAttribute(MARGINTOP)); + double marginBottom = Double.parseDouble(paper.getAttribute(MARGINBOTTOM)); + p.setSize(width, height); + p.setImageableArea(marginLeft, marginTop, width - (marginLeft + marginRight), height - (marginTop + marginBottom)); + + return p; + } + + /** + * Save the paper format + * @param p the Paper to save + */ + public static void savePaperFormat(Paper p) { + readDocument(); + + Element root = document.getDocumentElement(); + + NodeList profiles = root.getElementsByTagName(PROFILE); + Element scinotesProfile = (Element) profiles.item(0); + + NodeList allSizeElements = scinotesProfile.getElementsByTagName(PAPER); + Element paper = (Element) allSizeElements.item(0); + + if (paper == null) { + paper = document.createElement(PAPER); + scinotesProfile.appendChild((Node) paper); + } + + double width = p.getWidth(); + double height = p.getHeight(); + double marginLeft = p.getImageableX(); + double marginRight = width - (marginLeft + p.getImageableWidth()); + double marginTop = p.getImageableY(); + double marginBottom = height - (marginTop + p.getImageableHeight()); + + paper.setAttribute(WIDTH, Double.toString(width)); + paper.setAttribute(HEIGHT, Double.toString(height)); + paper.setAttribute(MARGINLEFT, Double.toString(marginLeft)); + paper.setAttribute(MARGINRIGHT, Double.toString(marginRight)); + paper.setAttribute(MARGINTOP, Double.toString(marginTop)); + paper.setAttribute(MARGINBOTTOM, Double.toString(marginBottom)); + + writeDocument(); + } + + /** + * @return the color the altern colors for inner function + */ + public static Color[] getAlternColors() { + readDocument(); + + Element root = document.getDocumentElement(); + + NodeList profiles = root.getElementsByTagName(PROFILE); + Element scinotesProfile = (Element) profiles.item(0); + + NodeList allSizeElements = scinotesProfile.getElementsByTagName(ALTERNCOLORS); + Element alternColors = (Element) allSizeElements.item(0); + Color[] arr = new Color[2]; + + Color c; + if (NULL.equals(alternColors.getAttribute(COLOR1))) { + c = null; + } else { + c = Color.decode(alternColors.getAttribute(COLOR1)); + } + + arr[0] = c; + + if (NULL.equals(alternColors.getAttribute(COLOR2))) { + c = null; + } else { + c = Color.decode(alternColors.getAttribute(COLOR2)); + } + + arr[1] = c; + return arr; + } + + /** + * Get all the recent opened files + * @return an array of uri + */ + public static List<File> getAllRecentOpenedFiles() { + List<File> files = new ArrayList<File>(); + readDocument(); + Element root = (Element) document.getDocumentElement().getElementsByTagName(RECENT_FILES).item(0); + if (root != null) { + NodeList recentFiles = root.getElementsByTagName(DOCUMENT); + for (int i = 0; i < recentFiles.getLength(); ++i) { + Element style = (Element) recentFiles.item(i); + + File temp = new File(style.getAttribute(PATH)); + + if (temp.exists()) { + files.add(temp); + } else { + root.removeChild((Node) style); + } + } + } + + clean(root); + writeDocument(); + + return files; + } + + /** + * Get all the favorite dirs + * @return a list of File + */ + public static List<File> getAllFavoriteDirs() { + List<File> dirsList = new ArrayList<File>(); + readDocument(); + Element root = (Element) document.getDocumentElement().getElementsByTagName(FAVORITE_DIRS).item(0); + if (root != null) { + NodeList dirs = root.getElementsByTagName(DIRECTORY); + for (int i = 0; i < dirs.getLength(); i++) { + Element dir = (Element) dirs.item(i); + File temp = new File(dir.getAttribute(PATH)); + + if (temp.exists()) { + dirsList.add(temp); + } else { + root.removeChild((Node) dir); + } + } + } + + clean(root); + writeDocument(); + + return dirsList; + } + + /** + * Add a path to a favorite directory + * @param path the path of the dir + */ + public static void saveFavoriteDirectory(String path) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(FAVORITE_DIRS).item(0); + Element newDir = document.createElement(DIRECTORY); + newDir.setAttribute(PATH, path); + root.appendChild((Node) newDir); + + clean(root); + writeDocument(); + } + + /** + * Remove the last favorite directory + */ + public static void rmLastFavoriteDirectory() { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(FAVORITE_DIRS).item(0); + NodeList dirs = root.getElementsByTagName(DIRECTORY); + + if (dirs.getLength() != 0) { + root.removeChild(dirs.item(dirs.getLength() - 1)); + } + + clean(root); + writeDocument(); + } + + /** + * Add a file to recent Opened Files + * @param filePath the path of the files to add + */ + public static void saveToRecentOpenedFiles(String filePath) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(RECENT_FILES).item(0); + NodeList recentFiles = root.getElementsByTagName(DOCUMENT); + int numberOfFiles = recentFiles.getLength(); + + // we remove all the duplicate + for (int i = 0; i < recentFiles.getLength(); ++i) { + Element style = (Element) recentFiles.item(i); + if (filePath.equals(style.getAttribute(PATH))) { + root.removeChild((Node) style); + numberOfFiles--; + } + } + + // if we have reached the maximun , we remove the oldest files + while (recentFiles.getLength() >= MAXRECENT) { + root.removeChild(root.getFirstChild()); + } + + Element newFile = document.createElement(DOCUMENT); + newFile.setAttribute(PATH, filePath); + root.appendChild((Node) newFile); + + clean(root); + writeDocument(); + } + + /** + * @return true if open files should be restored upon restart. + */ + public static boolean getRestoreOpenedFiles() { + readDocument(); + + Element root = document.getDocumentElement(); + + NodeList profiles = root.getElementsByTagName(PROFILE); + Element scinotesProfile = (Element) profiles.item(0); + + NodeList allSizeElements = scinotesProfile.getElementsByTagName(RESTOREFILES); + Element restorefiles = (Element) allSizeElements.item(0); + + return TRUE.equals(restorefiles.getAttribute(VALUE)); + } + + /** + * Active/deactive restoration of open files upon restart of scinotes + * @param activated active or not + */ + public static void saveRestoreOpenedFiles(boolean activated) { + readDocument(); + + Element root = document.getDocumentElement(); + + NodeList profiles = root.getElementsByTagName(PROFILE); + Element scinotesProfile = (Element) profiles.item(0); + + NodeList allSizeElements = scinotesProfile.getElementsByTagName(RESTOREFILES); + Element restorefiles = (Element) allSizeElements.item(0); + if (restorefiles == null) { + Element restoreElement = document.createElement(RESTOREFILES); + restorefiles.setAttribute(VALUE, new Boolean(activated).toString()); + restorefiles.appendChild((Node) restoreElement); + } else { + restorefiles.setAttribute(VALUE, new Boolean(activated).toString()); + } + + clean(root); + writeDocument(); + } + + /** + * Return a count of the open files that exist. New files, for instance, do not. + * @return count + */ + public static int countExistingOpenFiles(UUID uuid) { + int count = 0; + readDocument(); + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + if (root != null) { + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + for (int i = 0; i < openFiles.getLength(); ++i) { + Element style = (Element) openFiles.item(i); + if (style.getAttribute(EDITORINST).equals(uuid.toString())) { + File temp = new File(style.getAttribute(PATH)); + if (temp.exists()) { + count++; + } + } + } + } + return count; + } + + /** + * Get the list of open files associated with an editor instance hashcode. + * Only files that exist are returned. + * @param editorID unique id of an editor instance + * @return an array of uri + */ + public static List<File> getOpenFilesByEditor(UUID editorID) { + List<File> files = new ArrayList<File>(); + readDocument(); + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + if (root != null) { + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + + /* Loop through the list and return only the files with a matching hash code. */ + int i = 0; + for (; i < openFiles.getLength(); i++) { + Element doc = (Element) openFiles.item(i); + + if (editorID.equals(UUID.fromString(doc.getAttribute(EDITORINST)))) { + File temp = new File(doc.getAttribute(PATH)); + + /* Check that the file exists and add to file list or else remove the node. */ + if (temp.exists() && !files.contains(temp)) { + files.add(temp); + } else { + root.removeChild((Node) doc); + i--; // Adjust index to account for removed item. + } + } + } + + clean(root); + writeDocument(); + } + return files; + } + + /** + * Get a list of unique editor instance identifiers in the list of open files. + * @return an array of editor instance identifiers + */ + public static List<UUID> getOpenFilesEditorList() { + List<UUID> editorIDlist = new ArrayList<UUID>(); + readDocument(); + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + if (root != null) { + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + + /* Loop through the list and return the list of IDs. */ + for (int i = 0; i < openFiles.getLength(); ++i) { + Element style = (Element) openFiles.item(i); + + UUID editorID = UUID.fromString(style.getAttribute(EDITORINST)); + + if (!editorIDlist.contains(editorID)) { + editorIDlist.add(editorID); + } + } + } + return editorIDlist; + } + + /** + * Add a file to currently open files + * @param filePath the path of the files to add + * @param editorInstance instance of the editor to associate with the open file + * @param sep the pane + */ + public static void saveToOpenFiles(String filePath, SciNotes editorInstance, ScilabEditorPane sep) { + saveToOpenFiles(filePath, editorInstance, sep, -1); + } + + /** + * Add a file to currently open files + * @param filePath the path of the files to add + * @param editorInstance instance of the editor to associate with the open file + * @param sep the pane + */ + public static void saveToOpenFiles(String filePath, SciNotes editorInstance, ScilabEditorPane sep, int pos) { + readDocument(); + removeFromOpenFiles(editorInstance.getUUID(), Arrays.asList(new String[] {filePath})); + UUID nil = new UUID(0, 0); + + // Find the element containing the list of open files + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + // Get the list of open files + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + int numberOfFiles = openFiles.getLength(); + + Node bef = null; + if (pos != - 1 && pos < numberOfFiles) { + bef = openFiles.item(pos); + } + + Element newFile = document.createElement(DOCUMENT); + newFile.setAttribute(PATH, filePath); + // Record the editor instance's hash code + newFile.setAttribute(EDITORINST, editorInstance.getUUID().toString()); + //root.appendChild((Node) newFile); + // Record the text pane's hash code + newFile.setAttribute(PANEINST, sep.getUUID().toString()); + newFile.setAttribute(PANEINST_EX, nil.toString()); + if (bef != null) { + root.insertBefore((Node) newFile, bef); + } else { + root.appendChild((Node) newFile); + } + + clean(root); + writeDocument(); + } + + /** + * Remove a tab with an open file from the list of open files + * @param editorInstance instance of the editor + * @param sep instance of the editor pane. + */ + public static void removeFromOpenFiles(SciNotes editorInstance, ScilabEditorPane sep) { + removeFromOpenFiles(editorInstance.getUUID(), sep.getUUID()); + } + + /** + * Remove from the list of open files all files with a matching editor instance identifer + * @param editorID editor instance identifer + */ + public static void removeFromOpenFiles(UUID editorID) { + removeFromOpenFiles(editorID, new UUID(0, 0) /* nil UUID */); + } + + /** + * Remove a tab with an open file from the list of open files + * @param editorID editor instance identifer + * @param sepID editor pane instance identifer. If a nil UUID is passed, + * all files with a matching editor instance identifer are removed. + */ + public static void removeFromOpenFiles(UUID editorID, List<String> toRemove) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + + // Remove item with matching editorID and sepID. + for (int i = openFiles.getLength() - 1; i >= 0; i--) { + Element doc = (Element) openFiles.item(i); + if (editorID.equals(UUID.fromString(doc.getAttribute(EDITORINST))) + && toRemove.contains(doc.getAttribute(PATH))) { + root.removeChild((Node) doc); + } + } + + clean(root); + writeDocument(); + } + + /** + * Remove a tab with an open file from the list of open files + * @param editorID editor instance identifer + * @param sepID editor pane instance identifer. If a nil UUID is passed, + * all files with a matching editor instance identifer are removed. + */ + public static void removeFromOpenFiles(UUID editorID, UUID sepID) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + + // Remove item with matching editorID and sepID. + UUID nil = new UUID(0, 0); + for (int i = openFiles.getLength() - 1; i >= 0; i--) { + Element style = (Element) openFiles.item(i); + UUID paneID1 = UUID.fromString(style.getAttribute(PANEINST)); + UUID paneID2 = UUID.fromString(style.getAttribute(PANEINST_EX)); + + if (editorID.equals(UUID.fromString(style.getAttribute(EDITORINST))) + && (sepID.equals(nil) || sepID.equals(paneID1) || sepID.equals(paneID2))) { + root.removeChild((Node) style); + } + } + + clean(root); + writeDocument(); + } + + /** + * Change a filename. + * @param newfilePath new pathname of the file + * @param editorInstance instance of the editor + * @param sep instance of the editor pane + */ + public static void renameOpenFilesItem(String newfilePath, SciNotes editorInstance, ScilabEditorPane sep) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + Element style = findOpenFileItem(root, editorInstance.getUUID(), sep.getUUID()); + + if (style != null) { + style.setAttribute(PATH, newfilePath); + } + + /* Save changes */ + writeDocument(); + } + + /** + * Replace a single text pane ID with two pane IDs when a tab split occurs + * @param editorInstance instance of the editor + * @param old1 old instance of the editor pane + * @param new1 first new instance of the tabbed editor pane + * @param new2 second new instance of the tabbed editor pane + */ + public static void tabSplitOpenFilesItem(SciNotes editorInstance, ScilabEditorPane old1, ScilabEditorPane new1, ScilabEditorPane new2) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + Element style = findOpenFileItem(root, editorInstance.getUUID(), old1.getUUID()); + + if (style != null) { + style.setAttribute(PANEINST, new1.getUUID().toString()); + style.setAttribute(PANEINST_EX, new2.getUUID().toString()); + } + + /* Save changes */ + writeDocument(); + } + + /** + * Replace double pane IDs with a single ID when a tabbed pane is replaced by a single pane. + * @param editorInstance instance of the editor + * @param old1 one of the old tabbed editor pane + * @param new1 new editor pane + */ + public static void removeTabSplitInOpenFilesItem(SciNotes editorInstance, ScilabEditorPane old1, ScilabEditorPane new1) { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + Element style = findOpenFileItem(root, editorInstance.getUUID(), old1.getUUID()); + + if (style != null) { + UUID nil = new UUID(0, 0); + style.setAttribute(PANEINST, new1.getUUID().toString()); + style.setAttribute(PANEINST_EX, nil.toString()); + } + + /* Save changes */ + writeDocument(); + } + + /** + * Find the first element with matching editor and pane identifiers + * @param root Document root + * @param editorID instance of the editor to find + * @param sepID instance of the editor pane to find + * @return the corresponding element + */ + public static Element findOpenFileItem(Element root, UUID editorID, UUID sepID) { + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + + // Find item with matching editor and pane IDs + for (int i = 0; i < openFiles.getLength(); i++) { + Element style = (Element) openFiles.item(i); + UUID paneID1 = UUID.fromString(style.getAttribute(PANEINST)); + UUID paneID2 = UUID.fromString(style.getAttribute(PANEINST_EX)); + + if (editorID.equals(UUID.fromString(style.getAttribute(EDITORINST))) + && (sepID.equals(paneID1) || sepID.equals(paneID2))) { + return style; + } + } + + return null; + } + + /** + * Empty the list of open files. Performed when the editor is opened + * and the user opts not to restore the open files. + */ + public static void removeAllOpenFiles() { + readDocument(); + + Element root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + + // Remove all + for (int i = openFiles.getLength() - 1; i >= 0; --i) { + Element style = (Element) openFiles.item(i); + root.removeChild((Node) style); + } + + clean(root); + writeDocument(); + } + + /** + * Reset the current conf file + */ + public static void resetDocument() { + document = null; + } + + /** + * Read the file to modify + */ + private static void readDocument() { + readDocument(USER_SCINOTES_CONFIG_FILE); + } + + /** + * Read the file to modify + */ + private static void readDocument(String pathConfSci) { + File fileConfig = new File(USER_SCINOTES_CONFIG_FILE); + if (!fileConfig.exists()) { + createUserCopy(); + } + File xml = null; + DocumentBuilder docBuilder = null; + String factoryName = ScilabDocumentBuilderFactory.useDefaultDocumentBuilderFactoryImpl(); + + try { + if (document == null) { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + docBuilder = factory.newDocumentBuilder(); + + // read content of a XML file with DOM + xml = new File(pathConfSci); + document = docBuilder.parse(xml); + } + } catch (ParserConfigurationException pce) { + System.err.println(ERROR_READ + pathConfSci); + } catch (SAXException se) { + System.err.println(ERROR_READ + pathConfSci); + } catch (IOException ioe) { + System.err.println(ERROR_READ + pathConfSci); + } + + ScilabDocumentBuilderFactory.restoreDocumentBuilderFactoryImpl(factoryName); + + if (document == null && fileConfig.exists()) { + ScilabModalDialog.show(null, SciNotesMessages.CORRUPTED_CONF_FILE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + fileConfig.delete(); + createUserCopy(); + readDocument(pathConfSci); + } + } + + /** + * Save the modifications + */ + private static void writeDocument() { + if (mustSave) { + ScilabXMLUtilities.writeDocument(document, USER_SCINOTES_CONFIG_FILE); + } + } + + /** + * + */ + public static void saveCodeNavigatorState(String editorUUID, String navUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList navs = root.getElementsByTagName(CODENAVIGATOR); + boolean update = false; + for (int i = 0; i < navs.getLength(); i++) { + Element nav = (Element) navs.item(i); + if (nav.getAttribute("uuid").equals(navUUID)) { + nav.setAttribute("depends", editorUUID); + update = true; + break; + } + } + + if (!update) { + ScilabXMLUtilities.createNode(document, root, CODENAVIGATOR, new String[] {"uuid", navUUID, "depends", editorUUID}); + } + + writeDocument(); + } + + /** + * + */ + public static String getCodeNavigatorState(String navUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList navs = root.getElementsByTagName(CODENAVIGATOR); + for (int i = 0; i < navs.getLength(); i++) { + Element nav = (Element) navs.item(i); + if (nav.getAttribute("uuid").equals(navUUID)) { + return nav.getAttribute("depends"); + } + } + return null; + } + + /** + * + */ + public static String getCodeNavigatorStateForEditor(String editorUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList navs = root.getElementsByTagName(CODENAVIGATOR); + for (int i = 0; i < navs.getLength(); i++) { + Element nav = (Element) navs.item(i); + if (nav.getAttribute("depends").equals(editorUUID)) { + return nav.getAttribute("uuid"); + } + } + return null; + } + + /** + * + */ + public static void saveSearchInFilesState(String editorUUID, String sfUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList sfs = root.getElementsByTagName(SEARCHINFILES); + boolean update = false; + for (int i = 0; i < sfs.getLength(); i++) { + Element sf = (Element) sfs.item(i); + if (sf.getAttribute("uuid").equals(sfUUID)) { + sf.setAttribute("depends", editorUUID); + update = true; + break; + } + } + + if (!update) { + ScilabXMLUtilities.createNode(document, root, SEARCHINFILES, new String[] {"uuid", sfUUID, "depends", editorUUID}); + } + + writeDocument(); + } + + /** + * + */ + public static String getSearchInFilesState(String sfUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList sfs = root.getElementsByTagName(SEARCHINFILES); + for (int i = 0; i < sfs.getLength(); i++) { + Element sf = (Element) sfs.item(i); + if (sf.getAttribute("uuid").equals(sfUUID)) { + return sf.getAttribute("depends"); + } + } + return null; + } + + /** + * + */ + public static String getSearchInFilesStateForEditor(String editorUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList sfs = root.getElementsByTagName(SEARCHINFILES); + for (int i = 0; i < sfs.getLength(); i++) { + Element sf = (Element) sfs.item(i); + if (sf.getAttribute("depends").equals(editorUUID)) { + return sf.getAttribute("uuid"); + } + } + return null; + } + + /** + * + */ + public static void saveEditorUUID(String editorUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList eis = root.getElementsByTagName(EDITORUUID); + for (int i = 0; i < eis.getLength(); i++) { + Element ei = (Element) eis.item(i); + if (ei.getAttribute("uuid").equals(editorUUID)) { + return; + } + } + + ScilabXMLUtilities.createNode(document, root, EDITORUUID, new String[] {"uuid", editorUUID}); + + writeDocument(); + } + + /** + * + */ + public static void removeEditorUUID(String editorUUID) { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList eis = root.getElementsByTagName(EDITORUUID); + for (int i = 0; i < eis.getLength(); i++) { + Element ei = (Element) eis.item(i); + if (ei.getAttribute("uuid").equals(editorUUID)) { + root.removeChild(ei); + } + } + + root = (Element) document.getDocumentElement().getElementsByTagName(OPEN_FILES).item(0); + if (root != null) { + NodeList openFiles = root.getElementsByTagName(DOCUMENT); + for (int i = 0; i < openFiles.getLength(); ++i) { + Element of = (Element) openFiles.item(i); + if (of.getAttribute(EDITORINST).equals(editorUUID)) { + root.removeChild(of); + } + } + } + + writeDocument(); + } + + /** + * + */ + public static List<String> getEditorsUUID() { + readDocument(); + + Element root = document.getDocumentElement(); + NodeList eis = root.getElementsByTagName(EDITORUUID); + List<String> list = new ArrayList<String>(); + for (int i = 0; i < eis.getLength(); i++) { + Element ei = (Element) eis.item(i); + list.add(ei.getAttribute("uuid")); + } + + return list; + } + + /** + * Add a file to recent Opened Files + * @param exp the path of the files to add + */ + public static void saveRecentSearch(String exp) { + Node root = getXcosRoot(); + if (root == null || exp == null || exp.compareTo("") == 0) { + return; + } + + Node recents = getNodeChild(root, RECENT_SEARCH); + if (recents == null) { + recents = document.createElement(RECENT_SEARCH); + root.appendChild(recents); + } + + List<Node> search = getNodeChildren(recents, SEARCH); + + while (search.size() >= MAXRECENT) { + removeRecentSearch(((Element) search.get(0)).getAttribute(EXPRESSION)); + search = getNodeChildren(recents, SEARCH); + } + //if path already in file no need to add it + for (Node item : search) { + if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) { + return; + } + } + + Element newSearch = document.createElement(SEARCH); + newSearch.setAttribute(EXPRESSION, exp); + recents.appendChild((Node) newSearch); + + clean(recents); + writeDocument(); + } + + /** + * @param exp the expression to remove + */ + public static void removeRecentSearch(String exp) { + Node root = getXcosRoot(); + if (root == null) { + return; + } + + Node recent = getNodeChild(root, RECENT_SEARCH); + List<Node> search = getNodeChildren(recent, SEARCH); + + // remove node if exists + for (Node file : search) { + if (exp.compareTo(((Element) file).getAttribute(EXPRESSION)) == 0) { + recent.removeChild(file); + break; + } + } + + clean(recent); + writeDocument(); + + } + + /** + * @return a list of the recent searches + */ + public static List<String> getRecentSearch() { + List<String> files = new ArrayList<String>(); + + Node root = getXcosRoot(); + if (root == null) { + return files; + } + + Node recent = getNodeChild(root, RECENT_SEARCH); + List<Node> searches = getNodeChildren(recent, SEARCH); + for (Node search : searches) { + String exp = ((Element) search).getAttribute(EXPRESSION); + if (exp != null && exp.compareTo("") != 0) { + files.add(exp); + } + } + + return files; + } + + /** + * Add a file to recent Opened Files + * @param exp the path of the files to add + */ + public static void saveRecent(String exp, String nodeName, String childNodeName) { + Node root = getXcosRoot(); + if (root == null || exp == null || exp.compareTo("") == 0) { + return; + } + + Node recents = getNodeChild(root, nodeName); + if (recents == null) { + recents = document.createElement(nodeName); + root.appendChild(recents); + } + + List<Node> list = getNodeChildren(recents, childNodeName); + + while (list.size() >= MAXRECENT) { + removeRecent(((Element) list.get(0)).getAttribute(EXPRESSION), nodeName, childNodeName); + list = getNodeChildren(recents, childNodeName); + } + //if path already in file no need to add it + for (Node item : list) { + if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) { + return; + } + } + + Element newNode = document.createElement(childNodeName); + newNode.setAttribute(EXPRESSION, exp); + recents.appendChild((Node) newNode); + + clean(recents); + writeDocument(); + } + + /** + * @param exp the expression to remove + */ + public static void removeRecent(String exp, String nodeName, String childNodeName) { + Node root = getXcosRoot(); + if (root == null) { + return; + } + + Node recent = getNodeChild(root, nodeName); + List<Node> list = getNodeChildren(recent, childNodeName); + + // remove node if exists + for (Node item : list) { + if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) { + recent.removeChild(item); + break; + } + } + + clean(recent); + writeDocument(); + } + + /** + * @return a list of the recent searches + */ + public static List<String> getRecent(String nodeName, String childNodeName) { + List<String> files = new ArrayList<String>(); + + Node root = getXcosRoot(); + if (root == null) { + return files; + } + + Node recent = getNodeChild(root, nodeName); + List<Node> list = getNodeChildren(recent, childNodeName); + for (Node node : list) { + String exp = ((Element) node).getAttribute(EXPRESSION); + if (exp != null && exp.compareTo("") != 0) { + files.add(exp); + } + } + + return files; + } + + + /** + * @param exp the recent expression for a replacement + */ + public static void saveRecentReplace(String exp) { + Node root = getXcosRoot(); + if (root == null || exp == null || exp.compareTo("") == 0) { + return; + } + + Node recent = getNodeChild(root, RECENT_REPLACE); + if (recent == null) { + recent = document.createElement(RECENT_REPLACE); + root.appendChild(recent); + } + + List<Node> replace = getNodeChildren(recent, REPLACE); + + while (replace.size() >= MAXRECENT) { + removeRecentReplace(((Element) replace.get(0)).getAttribute(EXPRESSION)); + replace = getNodeChildren(recent, REPLACE); + } + //if path already in file no need to add it + for (Node item : replace) { + if (exp.compareTo(((Element) item).getAttribute(EXPRESSION)) == 0) { + return; + } + } + + Element newReplace = document.createElement(REPLACE); + newReplace.setAttribute(EXPRESSION, exp); + recent.appendChild((Node) newReplace); + + clean(recent); + writeDocument(); + } + + /** + * @param filePath remove recent replace in the this file + */ + public static void removeRecentReplace(String filePath) { + + Node root = getXcosRoot(); + if (root == null) { + return; + } + + Node recent = getNodeChild(root, RECENT_REPLACE); + List<Node> replace = getNodeChildren(recent, REPLACE); + + // remove node if exists + for (Node exp : replace) { + if (filePath.compareTo(((Element) exp).getAttribute(EXPRESSION)) == 0) { + recent.removeChild(exp); + break; + } + + } + + clean(recent); + writeDocument(); + + } + + /** + * @return the recent replace + */ + public static List<String> getRecentReplace() { + List<String> exps = new ArrayList<String>(); + + Node root = getXcosRoot(); + if (root == null) { + return exps; + } + + Node recent = getNodeChild(root, RECENT_REPLACE); + List<Node> replace = getNodeChildren(recent, REPLACE); + for (Node file : replace) { + String exp = ((Element) file).getAttribute(EXPRESSION); + if (exp != null && exp.compareTo("") != 0) { + exps.add(exp); + } + } + + return exps; + } + + /** + * @return true for a regexp search + */ + public static boolean getRegularExpression() { + return getBooleanAttribute(REGULAR_EXPRESION, STATE_FLAG, false); + } + + /** + * @param regualExp for a regexp search + */ + public static void saveRegularExpression(boolean regualExp) { + saveBooleanAttribute(REGULAR_EXPRESION, STATE_FLAG, regualExp); + } + + /** + * @return true for a wholeWord search + */ + public static boolean getWholeWord() { + return getBooleanAttribute(WHOLE_WORD, STATE_FLAG, false); + } + + /** + * @param wholeWord for a wholeWord search + */ + public static void saveWholeWord(boolean wholeWord) { + saveBooleanAttribute(WHOLE_WORD, STATE_FLAG, wholeWord); + } + + /** + * @return true for a recursive search + */ + public static boolean getRecursive() { + return getBooleanAttribute(RECURSIVE, STATE_FLAG, true); + } + + /** + * @param recursive for a recursive search + */ + public static void saveRecursive(boolean recursive) { + saveBooleanAttribute(RECURSIVE, STATE_FLAG, recursive); + } + + /** + * @return true for a line by line search + */ + public static boolean getLineByLine() { + return getBooleanAttribute(LINEBYLINE, STATE_FLAG, true); + } + + /** + * @param lineByLine for a line by line search + */ + public static void saveLineByLine(boolean lineByLine) { + saveBooleanAttribute(LINEBYLINE, STATE_FLAG, lineByLine); + } + + /** + * @return true for a case sensitive file name + */ + public static boolean getFileCase() { + return getBooleanAttribute(FILECASE, STATE_FLAG, false); + } + + /** + * @param fileCase for a case sensitive file name + */ + public static void saveFileCase(boolean fileCase) { + saveBooleanAttribute(FILECASE, STATE_FLAG, fileCase); + } + + /** + * @return true for a circular search + */ + public static boolean getCircularSearch() { + return getBooleanAttribute(CIRCULAR, STATE_FLAG, true); + } + + /** + * @param circular is true for a circular search + */ + public static void saveCircularSearch(boolean circular) { + saveBooleanAttribute(CIRCULAR, STATE_FLAG, circular); + } + + /** + * @return true for a case sensitive search + */ + public static boolean getCaseSensitive() { + return getBooleanAttribute(CASE_SENSITIVE, STATE_FLAG, false); + } + + /** + * @param caseSensitive for a case sensitive search + */ + public static void saveCaseSensitive(boolean caseSensitive) { + saveBooleanAttribute(CASE_SENSITIVE, STATE_FLAG, caseSensitive); + } + + /** + * getBooleanAttribute + * @param node the node name + * @param attrib the attribute of the node + * @param defaultValue true or false + * @return the found boolean value or defaultValue if not found + */ + private static boolean getBooleanAttribute(String node, String attrib, boolean defaultValue) { + boolean flag = false; + Node root = getXcosRoot(); + if (root == null) { + return flag; + } + Node recent = getNodeChild(root, node); + if (recent != null) { + String exp = ((Element) recent).getAttribute(attrib); + if (exp.compareTo(TRUE) == 0) { + flag = true; + } + } else { + return defaultValue; + } + return flag; + } + + /** + * saveBooleanAttribute + * @param node the node name + * @param attrib the attribute of the node + * @param state "true" or "false" + */ + private static void saveBooleanAttribute(String node, String attrib, boolean state) { + Node root = getXcosRoot(); + if (root == null) { + return; + } + + Node recent = getNodeChild(root, node); + if (recent == null) { + recent = document.createElement(node); + root.appendChild(recent); + } + + + ((Element) recent).setAttribute(attrib, new Boolean(state).toString()); + + root.appendChild(recent); + + /* Save changes */ + writeDocument(); + } + + /** + * getNodeChild + * @param par parent + * @param nodeName the name + * @return the node + */ + private static Node getNodeChild(Node par, String nodeName) { + Node parent = par; + if (parent == null) { + if (document == null) { + readDocument(); + if (document == null) { + return null; + } + } + parent = document; + } + + Node currentNode = parent.getFirstChild(); + while (currentNode != null) { + if (currentNode.getNodeName().compareTo(nodeName) == 0) { + return currentNode; + } + currentNode = currentNode.getNextSibling(); + } + return currentNode; + } + + /** + * getNodeChildren + * @param par parent + * @param childName the name + * @return a list of nodes + */ + private static List<Node> getNodeChildren(Node par, String childName) { + Node parent = par; + List<Node> nodes = new ArrayList<Node>(); + if (parent == null) { + if (document == null) { + readDocument(); + if (document == null) { + return nodes; + } + } + parent = document; + } + + Node currentNode = parent.getFirstChild(); + while (currentNode != null) { + if (currentNode.getNodeName().compareTo(childName) == 0) { + nodes.add(currentNode); + } + currentNode = currentNode.getNextSibling(); + } + return nodes; + + } + + /** + * @return the root + */ + private static Node getXcosRoot() { + if (document == null) { + readDocument(); + if (document == null) { + return null; + } + } + + Node setting = getNodeChild(null, SETTING); + + if (setting != null) { + List<Node> nodes = getNodeChildren(setting, PROFILE); + for (Node node : nodes) { + if (((Element) node).getAttribute(NAME).compareTo(SCINOTES) == 0) { + return node; + } + } + } + return null; + } + + /** + * Remove text at the beginning and at the end + * @param r the element to clean + */ + private static void clean(Node r) { + ScilabXMLUtilities.removeEmptyLines(r); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/DropFilesListener.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/DropFilesListener.java new file mode 100755 index 000000000..cbcf17d7f --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/DropFilesListener.java @@ -0,0 +1,218 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2010 - Calixte DENIZET + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Point; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.io.IOException; + +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; + +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * DropFiles Listener + * @author Allan CORNET + * @author Calixte DENIZET + * + */ +public class DropFilesListener implements DropTargetListener { + + private DropTarget dropTarget; + private ScilabEditorPane pane; + private int p0; + private int p1; + private Point previousPoint = new Point(); + private Point actualPoint = new Point(); + private int actualPos; + private boolean enter; + + /** + * Constructor + * @param pane JEditorPane + */ + public DropFilesListener(ScilabEditorPane pane) { + this.pane = pane; + dropTarget = new DropTarget(pane, DnDConstants.ACTION_COPY_OR_MOVE, this, true, null); + dropTarget.setActive(true); + } + + /** + * dragEnter + * @param arg0 DropTargetDragEvent + */ + public void dragEnter(DropTargetDragEvent arg0) { + if (arg0.isDataFlavorSupported(DataFlavor.stringFlavor)) { + int sp0 = pane.getSelectionStart(); + int sp1 = pane.getSelectionEnd(); + if (sp1 != sp0) { + p1 = sp1; + p0 = sp0; + } + enter = true; + } + } + + /** + * dragExit + * @param arg0 DropTargetEvent + */ + public void dragExit(DropTargetEvent arg0) { + if (enter) { + int y = actualPoint.y - previousPoint.y; + ScilabDocument doc = (ScilabDocument) pane.getDocument(); + Element root = doc.getDefaultRootElement(); + int line0 = root.getElementIndex(actualPos); + int line1 = Math.max(0, line0 + Math.min(root.getElementCount() - 1 - line0, (int) Math.signum(y) * y * y)); + int diff = actualPos - root.getElement(line0).getStartOffset(); + Element line = root.getElement(line1); + pane.setCaretPosition(Math.min(line.getStartOffset() + diff, line.getEndOffset() - 1)); + } + } + + /** + * dragOver + * @param arg0 DropTargetDragEven + */ + public void dragOver(DropTargetDragEvent arg0) { + if (arg0.isDataFlavorSupported(DataFlavor.stringFlavor)) { + previousPoint = actualPoint; + actualPoint = arg0.getLocation(); + actualPos = pane.viewToModel(actualPoint); + pane.setCaretPosition(actualPos); + } + } + + /** + * Drop handling + * @param arg0 the drop event + * @see java.awt.dnd.DropTargetListener#drop(java.awt.dnd.DropTargetDropEvent) + */ + @SuppressWarnings("unchecked") + public void drop(DropTargetDropEvent arg0) { + arg0.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE); + Transferable transferable = arg0.getTransferable(); + + try { + DataFlavor uriListFlavor = new DataFlavor("text/uri-list;class=java.lang.String"); + if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { + try { + java.util.List data = (java.util.List) transferable.getTransferData(DataFlavor.javaFileListFlavor); + for (int i = 0; i < data.size(); i++) { + SciNotes.getEditor().openFile(data.get(i).toString(), 0, null); + } + arg0.dropComplete(true); + } catch (UnsupportedFlavorException e) { + arg0.dropComplete(false); + return; + } catch (IOException e) { + arg0.dropComplete(false); + return; + } + + } else if (transferable.isDataFlavorSupported(uriListFlavor)) { + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4899516 + String uriData; + try { + uriData = (String) transferable.getTransferData(uriListFlavor); + } catch (UnsupportedFlavorException e) { + arg0.dropComplete(false); + return; + } catch (IOException e) { + arg0.dropComplete(false); + return; + } + java.util.List data = textURIListToFileList(uriData); + for (int i = 0; i < data.size(); i++) { + SciNotes.getEditor().openFile(data.get(i).toString(), 0, null); + } + arg0.dropComplete(true); + } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) { + try { + String dropString = (String) transferable.getTransferData(DataFlavor.stringFlavor); + ScilabDocument doc = (ScilabDocument) pane.getDocument(); + int pos = pane.viewToModel(arg0.getLocation()); + doc.mergeEditsBegin(); + if (arg0.getDropAction() == DnDConstants.ACTION_MOVE) { + doc.remove(p0, p1 - p0); + if (pos > p1) { + pos = pos - (p1 - p0); + } else if (pos > p0) { + pos = p0; + } + } + doc.insertString(pos, dropString, null); + doc.mergeEditsEnd(); + arg0.dropComplete(true); + } catch (UnsupportedFlavorException e) { + arg0.dropComplete(false); + return; + } catch (IOException e) { + arg0.dropComplete(false); + return; + } catch (BadLocationException e) { + arg0.dropComplete(false); + return; + } + } + } catch (ClassNotFoundException e1) { + arg0.dropComplete(false); + } + } + + /** + * dropActionChanged + * @param arg0 DropTargetDragEvent + */ + public void dropActionChanged(DropTargetDragEvent arg0) { + // TODO Auto-generated method stub + } + + /** + * textURIListToFileList + * @param data String URI + * @return java.util.List + */ + private static java.util.List textURIListToFileList(String data) { + java.util.List list = new java.util.ArrayList(1); + for (java.util.StringTokenizer st = new java.util.StringTokenizer(data, "\r\n"); + st.hasMoreTokens();) { + String s = st.nextToken(); + if (s.startsWith("#")) { + // the line is a comment (as per the RFC 2483) + continue; + } + try { + java.net.URI uri = new java.net.URI(s); + java.io.File file = new java.io.File(uri); + list.add(file); + } catch (java.net.URISyntaxException e) { + // malformed URI + } catch (IllegalArgumentException e) { + // the URI is not a valid 'file:' URI + } + } + return list; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/FOCodeConverter.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/FOCodeConverter.java new file mode 100755 index 000000000..0be2252ef --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/FOCodeConverter.java @@ -0,0 +1,148 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Color; +import java.awt.Font; +import java.awt.print.PageFormat; +import java.io.IOException; + +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * Code to XSL-FO converter Class + * @author Calixte DENIZET + */ +public class FOCodeConverter extends HTMLCodeConverter { + + private static final String ENTETE = "<?xml version=\"1.0\"?>\n" + + "<root xmlns=\"http://www.w3.org/1999/XSL/Format\">\n" + + "<layout-master-set>\n" + + "<simple-page-master master-name=\"content\"\n" + + "margin-right=\"MRin\"\n" + + "margin-left=\"MLin\"\n" + + "margin-bottom=\"MBin\"\n" + + "margin-top=\"MTin\"\n" + + "page-width=\"PWin\"\n" + + "page-height=\"PHin\">\n" + + "<region-body/>\n" + + "</simple-page-master>\n" + + "</layout-master-set>\n" + + "<page-sequence master-reference=\"content\">\n" + + "<flow flow-name=\"xsl-region-body\">"; + + private static final String END = "</flow></page-sequence></root>"; + + private int[] lineNumberArray; + + /** + * Constructor + * @param pane the ScilabEditorPane to convert (needed to have the context) + */ + public FOCodeConverter(ScilabEditorPane pane) { + super(pane); + } + + /** + * @param code the code to convert + * @param lineNumberArray an array of integers to number correctly the file (depends on whereami) + * @param format the page format to use + * @return the XSL-FO corresponding code + */ + public String convert(String code, int[] lineNumberArray, PageFormat format) { + this.printLineNumber = lineNumberArray != null; + this.lineNumberArray = lineNumberArray; + buffer.setLength(0); + Font f = ctx.tokenFonts[0]; + double ml = format.getImageableX() / 72; + double mr = (format.getWidth() - format.getImageableWidth()) / 72 - ml; + double mt = format.getImageableY() / 72; + double mb = (format.getHeight() - format.getImageableHeight()) / 72 - mt; + double pw = format.getWidth() / 72; + double ph = format.getHeight() / 72; + String entete = ENTETE.replace("MR", Double.toString(mr)).replace("ML", Double.toString(ml)).replace("MT", Double.toString(mt)).replace("MB", Double.toString(mb)).replace("PW", Double.toString(pw)).replace("PH", Double.toString(ph)); + buffer.append(entete); + buffer.append("<block white-space-treatment=\"preserve\" linefeed-treatment=\"preserve\" white-space-collapse=\"false\" hyphenate=\"false\" wrap-option=\"wrap\" font-family=\"" + f.getFamily() + "\" font-size=\"" + Float.toString(f.getSize2D() * 9f / 14f) + "pt\">"); + if (printLineNumber) { + String attr = "color=\"rgb(127,127,127)\" font-family=\"" + ctx.tokenFonts[0].getFamily() + "\" font-size=\"" + Float.toString(ctx.tokenFonts[0].getSize2D() * 9f / 14f) + "\""; + buffer.append("<inline " + attr + ">" + getStringInt(lineNumber++) + "</inline> "); + } + + return lexer.convert(this, code) + "</block>\n" + END; + } + + /** + * {@inheritDoc} + */ + public String convertColor(Color c) { + return " color=\"rgb(" + c.getRed() + "," + c.getGreen() + "," + c.getBlue() + ")\" "; + } + + /** + * {@inheritDoc} + */ + public String convertFont(Font f) { + String xml = ""; + if (f.isBold()) { + xml += "font-weight=\"bold\" "; + } + if (f.isItalic()) { + xml += "font-style=\"italic\" "; + } else { + xml += "font-style=\"normal\" "; + } + + return xml; + } + + /** + * {@inheritDoc} + */ + public String convertAttrib(int a) { + String xml = ""; + if ((a & 1) != 0) { + xml += " text-decoration=\"underline\" "; + } + if ((a & 2) != 0) { + xml += " text-decoration=\"line-through\" "; + } + + return xml; + } + + /** + * {@inheritDoc} + */ + public String convertTokenStyle(int tok, String contents) { + return "<inline " + convertColor(ctx.tokenColors[tok]) + convertFont(ctx.tokenFonts[tok]) + convertAttrib(ctx.tokenAttrib[tok]) + ">" + contents + "</inline>"; + } + + /** + * {@inheritDoc} + */ + public void handleNothing(String seq) throws IOException { + if (seq.equals("\n") && printLineNumber) { + String attr = "color=\"rgb(127,127,127)\" font-family=\"" + ctx.tokenFonts[0].getFamily() + "\" font-size=\"" + Float.toString(ctx.tokenFonts[0].getSize2D() * 9f / 14f) + "\""; + buffer.append("\n<inline " + attr + ">" + getStringInt(lineNumber++) + "</inline> "); + } else { + buffer.append(seq); + } + } + + /** + * {@inheritDoc} + */ + public String getStringInt(int n) { + return super.getStringInt(lineNumberArray[n - 1]); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/HTMLCodeConverter.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/HTMLCodeConverter.java new file mode 100755 index 000000000..a15f389ba --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/HTMLCodeConverter.java @@ -0,0 +1,281 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Color; +import java.awt.Font; +import java.io.IOException; + +import org.scilab.modules.scinotes.ScilabContext; +import org.scilab.modules.scinotes.ScilabEditorKit; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.ScilabLexerConstants; + +import org.scilab.modules.helptools.scilab.AbstractScilabCodeHandler; +import org.scilab.modules.helptools.scilab.ScilabLexer; + +/** + * Code converter Class + * @author Calixte DENIZET + */ +public class HTMLCodeConverter extends AbstractScilabCodeHandler { + + protected StringBuilder buffer = new StringBuilder(8192); + + protected ScilabContext ctx; + protected ScilabLexer lexer; + protected boolean printLineNumber; + protected int lineNumber = 1; + + /** + * Default constructor + * @param pane where the conversion occurs + */ + public HTMLCodeConverter(ScilabEditorPane pane) { + this.ctx = ((ScilabEditorKit) pane.getEditorKit()).getStylePreferences(); + this.lexer = new ScilabLexer(org.scilab.modules.scinotes.ScilabLexer.commands, org.scilab.modules.scinotes.ScilabLexer.macros); + } + + /** + * @param code the Scilab code to convert + * @param printLineNumber is true if the line numbers must be printed + * @return the converted code in HTML + */ + public String convert(String code, boolean printLineNumber) { + this.printLineNumber = printLineNumber; + buffer.setLength(0); + buffer.append("<pre style=\"font-family:" + ctx.tokenFonts[0].getFamily() + ";font-style:normal;font-size:" + Float.toString(ctx.tokenFonts[0].getSize2D()) + ";\">"); + if (printLineNumber) { + String attr = "font-family:" + ctx.tokenFonts[0].getFamily() + ";font-size:" + Float.toString(ctx.tokenFonts[0].getSize2D() * 9f / 14f) + ";"; + buffer.append("<span style=\"" + attr + "\">" + getStringInt(lineNumber++) + "</span> "); + } + return lexer.convert(this, code) + "</pre>"; + } + + /** + * @param c the color to convert + * @return the css color as rgb(R, G ,B); + */ + public String convertColor(Color c) { + return "color:rgb(" + c.getRed() + "," + c.getGreen() + "," + c.getBlue() + ");"; + } + + /** + * @param f the font to convert + * @return the css styles for a font + */ + public String convertFont(Font f) { + String html = ""; + if (f.isBold()) { + html += "font-weight:bold;"; + } + if (f.isItalic()) { + html += "font-style:italic;"; + } + + return html; + } + + /** + * @param a the attributes: 1 for underline & 2 for line-through + * @return the css styles for this text-decoration + */ + public String convertAttrib(int a) { + String html = ""; + if ((a & 1) != 0) { + html += "text-decoration:underline;"; + } + if ((a & 2) != 0) { + html += "text-decoration:line-through;"; + } + + return html; + } + + /** + * @param tok the kind of token according to ScilabLexerConstants + * @param contents contents to be enclosed + * @return a span with contents correctly decorated + */ + public String convertTokenStyle(int tok, String contents) { + return "<span style=\"" + convertColor(ctx.tokenColors[tok]) + convertFont(ctx.tokenFonts[tok]) + convertAttrib(ctx.tokenAttrib[tok]) + "\">" + contents + "</span>"; + } + + /** + * {@inheritDoc} + */ + public void handleDefault(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.DEFAULT, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleOperator(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.OPERATOR, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleOpenClose(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.OPENCLOSE, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleFKeywords(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.FKEYWORD, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleSKeywords(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.SKEYWORD, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleCKeywords(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.CKEYWORD, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleConstants(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.CONSTANTES, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleCommand(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.COMMANDS, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleMacro(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.MACROS, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleFunctionId(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.MACROINFILE, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleFunctionIdDecl(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.MACROINFILE, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleId(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.ID, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleInputOutputArgsDecl(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.INPUTOUTPUTARGS, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleInputOutputArgs(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.INPUTOUTPUTARGS, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleNumber(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.NUMBER, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleSpecial(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.SPECIAL, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleString(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.STRING, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleNothing(String seq) throws IOException { + if (seq.equals("\n") && printLineNumber) { + String attr = "font-family:" + ctx.tokenFonts[0].getFamily() + ";font-size:" + Float.toString(ctx.tokenFonts[0].getSize2D() * 9f / 14f) + ";"; + buffer.append("\n<span style=\"" + attr + "\">" + getStringInt(lineNumber++) + "</span> "); + } else { + buffer.append(seq); + } + } + + /** + * {@inheritDoc} + */ + public void handleField(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.FIELD, seq)); + } + + /** + * {@inheritDoc} + */ + public void handleComment(String seq) throws IOException { + buffer.append(convertTokenStyle(ScilabLexerConstants.COMMENT, seq)); + } + + /** + * {@inheritDoc} + */ + public String toString() { + return buffer.toString(); + } + + /** + * @param n the line number + * @return a string containing line number on 4 digits: 0001, 0002..., 9999 + */ + public String getStringInt(int n) { + if (n < 10) { + return "000" + n; + } else if (n < 100) { + return "00" + n; + } else if (n < 1000) { + return "0" + n; + } + + return Integer.toString(n); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/NavigatorWindow.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/NavigatorWindow.java new file mode 100755 index 000000000..101354e03 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/NavigatorWindow.java @@ -0,0 +1,930 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2010 - 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FocusTraversalPolicy; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.GroupLayout; +import javax.swing.GroupLayout.Alignment; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.text.Element; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; + +import org.flexdock.docking.event.DockingEvent; +import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem; +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.bridge.window.SwingScilabWindow; +import org.scilab.modules.gui.events.callback.CommonCallBack; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.menubar.MenuBar; +import org.scilab.modules.gui.menubar.ScilabMenuBar; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menuitem.ScilabMenuItem; +import org.scilab.modules.gui.tab.SimpleTab; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; +import org.scilab.modules.gui.textbox.ScilabTextBox; +import org.scilab.modules.gui.textbox.TextBox; +import org.scilab.modules.gui.toolbar.ToolBar; +import org.scilab.modules.gui.utils.ClosingOperationsManager; +import org.scilab.modules.gui.utils.WindowsConfigurationManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesGUI; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.tabfactory.CodeNavigatorTabFactory; + +/** + * + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public final class NavigatorWindow extends SwingScilabDockablePanel implements DocumentListener, + TreeExpansionListener { + + private static final String EMPTY = ""; + + private Map<ScilabEditorPane, DefaultMutableTreeNode> mapNode = new HashMap(); + private Map<ScilabEditorPane, TreePath> mapFunPath = new HashMap(); + private Map<ScilabEditorPane, TreePath> mapAnchorPath = new HashMap(); + private List<ScilabEditorPane> panes = new ArrayList<ScilabEditorPane>(); + + private SciNotes editor; + + private JTree functionNavigator; + private DefaultTreeModel model; + private ScilabEditorPane pane; + private ScilabDocument doc; + private boolean alphaOrder; + + private boolean isAbsolute = true; + private boolean lineNumberActive = true; + private boolean locked; + private boolean init; + + private JSeparator jSeparator1; + private JLabel labelGotoLine; + private JLabel labelNumerotation; + private JTextField lineNumber; + private JComboBox numType; + private JScrollPane scrollPane; + + private SwingScilabWindow parentWindow; + + static { + ScilabTabFactory.getInstance().addTabFactory(CodeNavigatorTabFactory.getInstance()); + } + + /** + * Creates new Navigator Window + */ + public NavigatorWindow(SciNotes editor, String uuid) { + super(SciNotesMessages.CODE_NAVIGATOR, uuid == null ? UUID.randomUUID().toString() : uuid); + this.editor = editor; + editor.addNavigator(this); + setContentPane(new javax.swing.JPanel()); + ConfigSciNotesManager.saveCodeNavigatorState(editor.getPersistentId(), getPersistentId()); + WindowsConfigurationManager.restorationFinished(this); + } + + /** + * Creates new Navigator Window + */ + public NavigatorWindow(SciNotes editor) { + this(editor, null); + } + + /** + * @param doc the doc to update + */ + public void update(ScilabDocument doc) { + if (!init) { + initTree(); + initComponents(); + functionNavigator.addTreeExpansionListener(this); + init = true; + } + + if (doc != null) { + if (this.doc != null) { + this.doc.removeDocumentListener(this); + } + + this.doc = doc; + this.pane = doc.getEditorPane(); + + this.doc.addDocumentListener(this); + + if (!mapNode.containsKey(pane)) { + initTree(); + } else { + updateTree(); + } + } + } + + public void addEditorPane(ScilabEditorPane pane) { + panes.add(pane); + update((ScilabDocument) pane.getDocument()); + } + + /** + * Update the navigator + */ + public void update() { + updateTree(); + } + + /** + * @param doc to use + */ + public void activateNavigator(ScilabDocument doc) { + initTree(); + update(doc); + } + + /** + * Set the parent window + */ + public void setParentWindow() { + this.parentWindow = SwingScilabWindow.createWindow(true); + parentWindow.addTab(this); + parentWindow.setVisible(true); + } + + /** + * Get the parent window id for this tab + * @return the id of the parent window + */ + public SwingScilabWindow getParentWindow() { + return this.parentWindow; + } + + /** + * {@inheritDoc} + */ + public SimpleTab getAsSimpleTab() { + return this; + } + + /** + * {@inheritDoc} + */ + public void addInfoBar(TextBox infoBarToAdd) { + setInfoBar(infoBarToAdd); + } + + /** + * {@inheritDoc} + */ + public void addMenuBar(MenuBar menuBarToAdd) { + setMenuBar(menuBarToAdd); + } + + /** + * {@inheritDoc} + */ + public void addToolBar(ToolBar toolBarToAdd) { + setToolBar(toolBarToAdd); + } + + /** + * Close this Navigator. + */ + public void closeNavigator() { + editor.removeNavigator(); + mapNode.clear(); + mapFunPath.clear(); + mapAnchorPath.clear(); + functionNavigator = null; + model = null; + pane = null; + doc = null; + for (ScilabEditorPane p : panes) { + ((ScilabDocument) p.getDocument()).removeDocumentListener(this); + } + panes.clear(); + } + + /** + * Nothing ! + * @param e the event + */ + public void changedUpdate(DocumentEvent e) { } + + /** + * Called when an insertion is made in the doc + * @param e the event + */ + public void insertUpdate(DocumentEvent e) { + handleEvent(e.getOffset(), e.getLength()); + } + + /** + * Called when a remove is made in the doc + * @param e the event + */ + public void removeUpdate(DocumentEvent e) { + handleEvent(e.getOffset(), e.getLength()); + } + + /** + * {@inheritDoc} + */ + public void dockingComplete(DockingEvent evt) { + super.dockingComplete(evt); + changeToolBar(); + } + + /** + * Try to add a SciNotes toolbar + */ + public void changeToolBar() { + SwingScilabWindow win = (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this); + if (win != null && win.getDockingPort() != null) { + Set<SwingScilabDockablePanel> set = (Set<SwingScilabDockablePanel>) win.getDockingPort().getDockables(); + for (SwingScilabDockablePanel tab : set) { + if (tab == editor) { + addToolBar(editor.getToolBar()); + break; + } + } + } + } + + /** + * {@inheritDoc} + */ + public void undockingComplete(DockingEvent evt) { + super.undockingComplete(evt); + addToolBar(null); + } + + /** + * {@inheritDoc} + */ + public void treeCollapsed(TreeExpansionEvent evt) { } + + /** + * {@inheritDoc} + */ + public void treeExpanded(TreeExpansionEvent evt) { + if (!locked) { + TreePath path = evt.getPath(); + DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); + ScilabEditorPane savePane = pane; + ScilabDocument saveDoc = doc; + boolean update = false; + if (node.getUserObject() instanceof String && SciNotesMessages.FUNCTIONS.equals(node.getUserObject())) { + pane = (ScilabEditorPane) ((DefaultMutableTreeNode) node.getParent()).getUserObject(); + doc = (ScilabDocument) pane.getDocument(); + locked = true; + updateFunctions(); + functionNavigator.expandPath(mapFunPath.get(pane)); + update = true; + } else if (node.getUserObject() instanceof String && SciNotesMessages.ANCHORS.equals(node.getUserObject())) { + pane = (ScilabEditorPane) ((DefaultMutableTreeNode) node.getParent()).getUserObject(); + doc = (ScilabDocument) pane.getDocument(); + locked = true; + updateAnchors(); + functionNavigator.expandPath(mapAnchorPath.get(pane)); + update = true; + } else if (node.getUserObject() instanceof ScilabEditorPane) { + pane = (ScilabEditorPane) node.getUserObject(); + doc = (ScilabDocument) pane.getDocument(); + boolean expanded = functionNavigator.isExpanded(mapFunPath.get(pane)); + updateFunctions(); + if (expanded) { + locked = true; + functionNavigator.expandPath(mapFunPath.get(pane)); + } + update = true; + } + if (update) { + pane = savePane; + doc = saveDoc; + } + } else { + locked = false; + } + } + + /** + * @param pane the pane which has been splitted + * @param split the new pane + */ + public void changePaneOnSplit(ScilabEditorPane pane, ScilabEditorPane split) { + if (mapNode.containsKey(pane)) { + DefaultMutableTreeNode node = mapNode.get(pane); + node.setUserObject(split); + mapNode.put(split, mapNode.get(pane)); + mapNode.remove(pane); + mapFunPath.put(split, mapFunPath.get(pane)); + mapFunPath.remove(pane); + mapAnchorPath.put(split, mapAnchorPath.get(pane)); + mapAnchorPath.remove(pane); + } + } + + /** + * @param pane to remove + */ + public void removePane(ScilabEditorPane pane) { + if (mapNode.containsKey(pane)) { + DefaultMutableTreeNode node = mapNode.get(pane); + ((DefaultMutableTreeNode) model.getRoot()).remove(node); + model.reload(); + mapNode.remove(pane); + mapFunPath.remove(pane); + mapAnchorPath.remove(pane); + panes.remove(pane); + this.pane = null; + this.doc = null; + } + } + + /** + * This method is called from within the constructor to + * initialize the form. + */ + private void initComponents() { + labelNumerotation = new JLabel(); + lineNumber = new JTextField(); + numType = new JComboBox(); + jSeparator1 = new JSeparator(); + labelGotoLine = new JLabel(); + scrollPane = new JScrollPane(); + + setTitle(SciNotesMessages.CODE_NAVIGATOR); + updateUI(); + + labelNumerotation.setText(SciNotesMessages.NUMEROTATION); + labelNumerotation.setFocusable(false); + + lineNumber.addKeyListener(new KeyListener() { + public void keyTyped(KeyEvent ke) { } + public void keyPressed(KeyEvent ke) { } + + public void keyReleased(KeyEvent ke) { + updateCaretPosition(); + } + }); + + lineNumber.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + updateCaretPosition(); + } + + public void focusLost(FocusEvent e) { + } + }); + + numType.setModel(new DefaultComboBoxModel(new String[] {SciNotesMessages.ABSOLUTE, SciNotesMessages.RELATIVE})); + numType.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + int i = numType.getSelectedIndex(); + if (i == 0 && !isAbsolute) { + lineNumber.setText(EMPTY); + isAbsolute = true; + } else if (i == 1 && isAbsolute) { + lineNumber.setText(EMPTY); + isAbsolute = false; + } + } + }); + + labelGotoLine.setText(SciNotesMessages.GO_TO_LINE); + labelGotoLine.setFocusable(false); + + functionNavigator.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + int row = functionNavigator.getRowForLocation(e.getX(), e.getY()); + if (e.getClickCount() == 2) { + handleSelectedItem(row); + } + } + }); + + functionNavigator.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "toggle"); + functionNavigator.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == '\n') { + int row = functionNavigator.getMinSelectionRow(); + handleSelectedItem(row); + } + } + }); + createPopupMenuOnJTree(); + + scrollPane.setViewportView(functionNavigator); + + /* Begin NetBeans */ + GroupLayout layout = new GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(scrollPane, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) + .addComponent(jSeparator1, GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(labelGotoLine) + .addComponent(labelNumerotation)) + .addGap(18, 18, 18) + .addGroup(layout.createParallelGroup(Alignment.LEADING) + .addComponent(lineNumber, GroupLayout.PREFERRED_SIZE, 58, GroupLayout.PREFERRED_SIZE) + .addComponent(numType, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)))) + .addContainerGap()) + ); + layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING) + .addGroup(Alignment.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 439, Short.MAX_VALUE) + .addPreferredGap(ComponentPlacement.RELATED) + .addComponent(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(labelGotoLine) + .addComponent(lineNumber, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addGap(4, 4, 4) + .addGroup(layout.createParallelGroup(Alignment.BASELINE) + .addComponent(labelNumerotation) + .addComponent(numType, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + /* End NetBeans */ + + List<Component> components = new ArrayList(3); + components.add(functionNavigator); + components.add(lineNumber); + components.add(numType); + setFocusable(true); + setFocusCycleRoot(true); + setFocusTraversalPolicy(new NavigatorFocusTraversalPolicy(components)); + + setMinimumSize(new Dimension(224, 0)); + setPreferredSize(new Dimension(224, 543)); + + CommonCallBack callback = new CommonCallBack(null) { + public void callBack() { + ClosingOperationsManager.startClosingOperation((SwingScilabDockablePanel) NavigatorWindow.this); + } + + public void actionPerformed(ActionEvent e) { + callBack(); + } + }; + + MenuBar menubar = ScilabMenuBar.createMenuBar(); + Menu fileMenu = ScilabMenu.createMenu(); + fileMenu.setText(SciNotesMessages.FILE); + fileMenu.setMnemonic('F'); + MenuItem menu = ScilabMenuItem.createMenuItem(); + menu.setCallback(callback); + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).setAccelerator(SciNotes.getActionKeys().get("scinotes-exit")); + menu.setText(SciNotesMessages.EXIT); + fileMenu.add(menu); + menubar.add(fileMenu); + + Menu orderMenu = ScilabMenu.createMenu(); + orderMenu.setText(SciNotesMessages.ORDER); + orderMenu.setMnemonic('O'); + menu = ScilabMenuItem.createMenuItem(); + menu.setCallback(new CommonCallBack(null) { + public void callBack() { + doc.setAlphaOrderInTree(true); + updateTree(); + } + + public void actionPerformed(ActionEvent e) { + callBack(); + } + }); + menu.setText(SciNotesMessages.ALPHABETIC_ORDER); + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).setAccelerator(KeyStroke.getKeyStroke("alt A")); + orderMenu.add(menu); + + menu = ScilabMenuItem.createMenuItem(); + menu.setCallback(new CommonCallBack(null) { + public void callBack() { + doc.setAlphaOrderInTree(false); + updateTree(); + } + + public void actionPerformed(ActionEvent e) { + callBack(); + } + }); + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).setAccelerator(KeyStroke.getKeyStroke("alt N")); + menu.setText(SciNotesMessages.NATURAL_ORDER); + orderMenu.add(menu); + + menubar.add(orderMenu); + addMenuBar(menubar); + + TextBox infobar = ScilabTextBox.createTextBox(); + addInfoBar(infobar); + } + + /** + * Init the tree + */ + public void initTree() { + mapNode.clear(); + mapFunPath.clear(); + if (functionNavigator == null) { + functionNavigator = new JTree(); + } + DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); + model = new DefaultTreeModel(root); + + for (ScilabEditorPane sep : panes) { + DefaultMutableTreeNode base = new DefaultMutableTreeNode(sep); + mapNode.put(sep, base); + DefaultMutableTreeNode funs = new DefaultMutableTreeNode(SciNotesMessages.FUNCTIONS); + ScilabDocument scidoc = (ScilabDocument) sep.getDocument(); + scidoc.fillTreeFuns(funs); + DefaultMutableTreeNode anchors = new DefaultMutableTreeNode(SciNotesMessages.ANCHORS); + scidoc.fillTreeAnchors(anchors); + base.add(funs); + base.add(anchors); + root.add(base); + mapFunPath.put(sep, new TreePath(model.getPathToRoot(funs))); + mapAnchorPath.put(sep, new TreePath(model.getPathToRoot(anchors))); + } + + functionNavigator.setModel(model); + functionNavigator.setRootVisible(false); + } + + /** + * Update the tree + */ + public void updateTree() { + DefaultMutableTreeNode current = mapNode.get(pane); + TreePath funPath = mapFunPath.get(pane); + TreePath anchorPath = mapAnchorPath.get(pane); + DefaultMutableTreeNode funs = (DefaultMutableTreeNode) current.getFirstChild(); + DefaultMutableTreeNode anchors = (DefaultMutableTreeNode) current.getChildAt(1); + boolean expFuns = false; + boolean expAnchors = false; + + if (functionNavigator.isExpanded(funPath) || funs.isLeaf()) { + current.removeAllChildren(); + funs.removeAllChildren(); + doc.fillTreeFuns(funs); + current.add(funs); + current.add(anchors); + model.reload(current); + expFuns = true; + } + + if (functionNavigator.isExpanded(anchorPath) || anchors.isLeaf()) { + current.removeAllChildren(); + anchors.removeAllChildren(); + doc.fillTreeAnchors(anchors); + current.add(funs); + current.add(anchors); + model.reload(current); + expAnchors = true; + } + + if (expFuns) { + functionNavigator.expandPath(funPath); + } + + if (expAnchors) { + functionNavigator.expandPath(anchorPath); + } + } + + /** + * Update a branch Functions in the tree + */ + private void updateFunctions() { + DefaultMutableTreeNode current = mapNode.get(pane); + DefaultMutableTreeNode funs = (DefaultMutableTreeNode) current.getFirstChild(); + DefaultMutableTreeNode anchors = (DefaultMutableTreeNode) current.getChildAt(1); + current.removeAllChildren(); + funs.removeAllChildren(); + doc.fillTreeFuns(funs); + current.add(funs); + current.add(anchors); + model.reload(current); + } + + /** + * Update a branch Anchors in the tree + */ + private void updateAnchors() { + DefaultMutableTreeNode current = mapNode.get(pane); + DefaultMutableTreeNode funs = (DefaultMutableTreeNode) current.getFirstChild(); + DefaultMutableTreeNode anchors = (DefaultMutableTreeNode) current.getChildAt(1); + current.removeAllChildren(); + anchors.removeAllChildren(); + doc.fillTreeAnchors(anchors); + current.add(funs); + current.add(anchors); + model.reload(current); + } + + /** + * Creates a popup menu on right click + */ + private void createPopupMenuOnJTree() { + final JPopupMenu popup = new JPopupMenu(); + + final JMenuItem alpha = new JMenuItem(SciNotesMessages.ALPHABETIC_ORDER); + final JMenuItem natural = new JMenuItem(SciNotesMessages.NATURAL_ORDER); + + alpha.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + handleOrder(true); + } + }); + popup.add(alpha); + + natural.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + handleOrder(false); + } + }); + popup.add(natural); + functionNavigator.setComponentPopupMenu(popup); + } + + /** + * @param alpha true for alphabetic order + */ + private void handleOrder(boolean alpha) { + int row = functionNavigator.getMinSelectionRow(); + if (row == -1) { + functionNavigator.setSelectionRow(0); + row = 0; + } + + TreePath path = functionNavigator.getPathForRow(row); + ScilabDocument saveDoc = doc; + ScilabEditorPane savePane = pane; + doc = getDocumentInNode((DefaultMutableTreeNode) path.getLastPathComponent()); + pane = getPaneInNode((DefaultMutableTreeNode) path.getLastPathComponent()); + doc.setAlphaOrderInTree(alpha); + updateTree(); + doc = saveDoc; + pane = savePane; + } + + /** + * Update the line numbering on a change in the document + * @param offset offset where the event occurred + * @param length length of inserted or removed text + */ + private void handleEvent(int offset, int length) { + Element root = doc.getDefaultRootElement(); + Element line = root.getElement(root.getElementIndex(offset)); + if (line instanceof ScilabDocument.ScilabLeafElement) { + ((ScilabDocument.ScilabLeafElement) line).resetType(); + updateTree(); + } + } + + /** + * Handle a selected item in the JTree + * @param row to handle + */ + private void handleSelectedItem(int row) { + TreePath path = functionNavigator.getPathForRow(row); + if (row != -1) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); + if (node.isLeaf() && node.getUserObject() instanceof ScilabDocument.ScilabLeafElement) { + ScilabEditorPane sep = (ScilabEditorPane) ((DefaultMutableTreeNode) node.getParent().getParent()).getUserObject(); + int pos = ((ScilabDocument.ScilabLeafElement) node.getUserObject()).getStartOffset(); + if (pos != -1) { + sep.getEditor().getTabPane().setSelectedComponent(sep.getEditorComponent()); + sep.scrollTextToPos(pos); + pos = sep.getDocument().getDefaultRootElement().getElementIndex(pos) + 1; + numType.setSelectedItem(SciNotesMessages.ABSOLUTE); + lineNumber.setText(Integer.toString(pos)); + } + } + } + } + + /** + * Update the caret position when a number is entered in the field + */ + private void updateCaretPosition() { + int line = 0; + boolean correct = false; + TreePath path = functionNavigator.getSelectionPath(); + DefaultMutableTreeNode node = null; + if (path != null) { + node = (DefaultMutableTreeNode) path.getLastPathComponent(); + } + + try { + line = Integer.decode(lineNumber.getText()).intValue(); + if (isAbsolute) { + correct = true; + line = correctLineNumber(line); + updatePaneDoc(node); + } else if (functionNavigator.getRowCount() >= 2) { + if (functionNavigator.isSelectionEmpty()) { + functionNavigator.setSelectionRow(1); + } + + if (node.isLeaf() && node.getUserObject() instanceof ScilabDocument.ScilabLeafElement) { + int pos = ((ScilabDocument.ScilabLeafElement) node.getUserObject()).getStartOffset(); + if (pos != -1) { + updatePaneDoc(node); + line += doc.getDefaultRootElement().getElementIndex(pos); + correct = true; + line = correctLineNumber(line); + } + } + } + } catch (NumberFormatException e) { + correct = false; + } + + setLineNumberColor(correct); + if (correct) { + pane.scrollTextToLineNumber(line, false); + } + } + + /** + * @param node corresponding to the pane to select + */ + private void updatePaneDoc(DefaultMutableTreeNode node) { + if (node != null) { + ScilabEditorPane sep = getPaneInNode(node); + if (sep != pane) { + pane = sep; + doc = (ScilabDocument) pane.getDocument(); + pane.getEditor().getTabPane().setSelectedComponent(pane.getEditorComponent()); + } + } + } + + /** + * @param node corresponding to the document to get + * @return the doc + */ + private ScilabDocument getDocumentInNode(DefaultMutableTreeNode node) { + return (ScilabDocument) getPaneInNode(node).getDocument(); + } + + /** + * @param node corresponding to the pane to get + * @return the pane + */ + private ScilabEditorPane getPaneInNode(DefaultMutableTreeNode node) { + if (node.isLeaf()) { + DefaultMutableTreeNode node1 = (DefaultMutableTreeNode) node.getParent(); + if (node1 != null) { + DefaultMutableTreeNode node2 = (DefaultMutableTreeNode) node1.getParent(); + if (node2 != null && node2.getUserObject() instanceof ScilabEditorPane) { + return (ScilabEditorPane) node2.getUserObject(); + } + } + } else if (node.getUserObject() instanceof String && SciNotesMessages.FUNCTIONS.equals(node.getUserObject())) { + return (ScilabEditorPane) ((DefaultMutableTreeNode) node.getParent()).getUserObject(); + } else if (node.getUserObject() instanceof ScilabEditorPane) { + return (ScilabEditorPane) node.getUserObject(); + } + + return pane; + } + + /** + * Checks if a line number is correct or not + * @param line the line number + * @return a correct line number + */ + private int correctLineNumber(int line) { + if (line < 0) { + return 0; + } + + int maxLine = doc.getDefaultRootElement().getElementCount(); + if (line >= maxLine) { + return maxLine - 1; + } + + return line; + } + + /** + * @param correct true if the lineNumber contains a number + */ + private void setLineNumberColor(boolean correct) { + if (correct && !lineNumberActive) { + lineNumber.setForeground(Color.BLACK); + lineNumberActive = true; + } else if (!correct && lineNumberActive) { + lineNumber.setForeground(Color.RED); + lineNumberActive = false; + } + } + + /** + * {@inheritDoc} + */ + private static class NavigatorFocusTraversalPolicy extends FocusTraversalPolicy { + + private List<Component> cycle; + + /** + * Default constructor + * @param cycle the componenents where the focus move + */ + public NavigatorFocusTraversalPolicy(List<Component> cycle) { + this.cycle = cycle; + } + + /** + * {@inheritDoc} + */ + public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { + int n = (cycle.indexOf(aComponent) + 1) % cycle.size(); + return cycle.get(n); + } + + /** + * {@inheritDoc} + */ + public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { + int n = (cycle.size() + cycle.indexOf(aComponent) - 1) % cycle.size(); + return cycle.get(n); + } + + /** + * {@inheritDoc} + */ + public Component getDefaultComponent(Container focusCycleRoot) { + return cycle.get(0); + } + + /** + * {@inheritDoc} + */ + public Component getLastComponent(Container focusCycleRoot) { + return cycle.get(cycle.size() - 1); + } + + /** + * {@inheritDoc} + */ + public Component getFirstComponent(Container focusCycleRoot) { + return cycle.get(0); + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SaveFile.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SaveFile.java new file mode 100755 index 000000000..d1f2f9313 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SaveFile.java @@ -0,0 +1,231 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + * + */ +package org.scilab.modules.scinotes.utils; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; + +import javax.swing.JEditorPane; +import javax.swing.text.BadLocationException; +import javax.swing.text.EditorKit; + +import org.scilab.modules.gui.messagebox.ScilabModalDialog; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.AnswerOption; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.ButtonType; +import org.scilab.modules.gui.messagebox.ScilabModalDialog.IconType; +import org.scilab.modules.scinotes.SciNotesAutosave; +import org.scilab.modules.scinotes.ScilabDocument; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SciNotesOptions; + +/** + * Save File utility class + * @author Allan CORNET + * @author Calixte DENIZET + */ +public final class SaveFile { + + private static final String LINE_SEPARATOR = "line.separator"; + + /** + * private Constructor + */ + private SaveFile() { } + + /** + * save text in JEditorPane + * @param textPane JEditorPane + * @param fOut File + * @param editorKit EditorKit + * @return true if saved + */ + public static boolean doSave(ScilabEditorPane textPane, int index, File fOut, EditorKit editorKit) { + return doSave(textPane, index, fOut, editorKit, true, false); + } + + /** + * save a document + * @param doc the document to save + * @param fOut File + * @param editorKit EditorKit + * @return true if saved + */ + public static boolean doSave(ScilabDocument doc, File fOut, EditorKit editorKit) throws IOException { + // get default eol + String defaultEol = System.getProperty(LINE_SEPARATOR); + boolean bReturn = false; + BufferedWriter bw = null; + OutputStreamWriter osw = null; + FileOutputStream fos = null; + + // set eol used to save file + if (doc.getEOL().compareTo(defaultEol) != 0) { + System.setProperty(LINE_SEPARATOR, doc.getEOL()); + } + + try { + fos = new FileOutputStream(fOut); + osw = new OutputStreamWriter(fos, SciNotesOptions.getSciNotesPreferences().encoding); + bw = new BufferedWriter(osw); + editorKit.write(bw, doc, 0, doc.getLength()); + bw.flush(); + bReturn = true; + } catch (BadLocationException e) { + System.err.println(e); + } finally { + try { + if (fos != null) { + fos.close(); + } + if (osw != null) { + osw.close(); + } + if (bw != null) { + bw.close(); + } + } catch (IOException e) { + System.err.println(e); + } + } + + // restore default eol + System.setProperty(LINE_SEPARATOR, defaultEol); + + return bReturn; + } + + /** + * save text in JEditorPane + * @param textPane JEditorPane + * @param fOut File + * @param editorKit EditorKit + * @return true if saved + */ + public static boolean doSave(ScilabEditorPane textPane, int index, File fOut, EditorKit editorKit, boolean addEOL, boolean silent) { + return doSave(textPane, index, fOut, editorKit, addEOL, silent, SciNotesOptions.getSciNotesAutosave().autoSave); + } + + /** + * save text in JEditorPane + * @param textPane JEditorPane + * @param fOut File + * @param editorKit EditorKit + * @return true if saved + */ + public static boolean doSave(ScilabEditorPane textPane, int index, File fOut, EditorKit editorKit, boolean addEOL, boolean silent, boolean backup) { + ScilabDocument styledDocument = (ScilabDocument) textPane.getDocument(); + boolean enc = false; + File backupOut = null; + if (!styledDocument.getEncoding().equalsIgnoreCase(SciNotesOptions.getSciNotesPreferences().encoding)) { + if (!silent) { + String msg = String.format(SciNotesMessages.DIFFERENT_ENCODINGS, styledDocument.getEncoding(), SciNotesOptions.getSciNotesPreferences().encoding); + if (ScilabModalDialog.show(textPane.getEditor(), msg, SciNotesMessages.DIFFERENT_ENCODINGS_TITLE, IconType.QUESTION_ICON, ButtonType.YES_NO) == AnswerOption.NO_OPTION) { + return false; + } + enc = true; + } else { + return false; + } + } + + if (backup) { + backupOut = SciNotesAutosave.getBackupFile(fOut.getName()); + } + + try { + fOut.createNewFile(); + if (backupOut != null) { + backupOut.createNewFile(); + } + } catch (IOException e) { + System.err.println(e); + } + + if (!fOut.canWrite()) { + if (!silent) { + ScilabModalDialog.show(textPane.getEditor(), SciNotesMessages.NOTWRITABLE, SciNotesMessages.SCINOTES_ERROR, IconType.ERROR_ICON); + } + return false; + } + + if (backupOut != null && !backupOut.canWrite()) { + backupOut = null; + } + + // get default eol + String defaultEol = System.getProperty(LINE_SEPARATOR); + + // set eol used to save file + if (styledDocument.getEOL().compareTo(defaultEol) != 0) { + System.setProperty(LINE_SEPARATOR, styledDocument.getEOL()); + } + if (addEOL) { + styledDocument.addEOL(); + } + + boolean bReturn = false; + + BufferedWriter bw = null; + OutputStreamWriter osw = null; + FileOutputStream fos = null; + + File[] files = new File[] {fOut, backupOut}; + + for (File file : files) { + if (file != null) { + try { + fos = new FileOutputStream(file); + osw = new OutputStreamWriter(fos, SciNotesOptions.getSciNotesPreferences().encoding); + bw = new BufferedWriter(osw); + editorKit.write(bw, styledDocument, 0, styledDocument.getLength()); + bw.flush(); + bReturn = true; + } catch (IOException e) { + System.err.println(e); + bReturn = false; + } catch (BadLocationException e) { + System.err.println(e); + bReturn = false; + } finally { + try { + if (fos != null) { + fos.close(); + } + if (osw != null) { + osw.close(); + } + if (bw != null) { + bw.close(); + } + } catch (IOException e) { + System.err.println(e); + } + } + } + } + + // restore default eol + System.setProperty(LINE_SEPARATOR, defaultEol); + if (enc) { + textPane.getEditor().reload(index); + } + + return bReturn; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesCompletionWindow.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesCompletionWindow.java new file mode 100755 index 000000000..6695875ec --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesCompletionWindow.java @@ -0,0 +1,151 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2007-2008 - INRIA - Vincent COUVERT + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Component; +import java.awt.Point; +import java.util.List; + +import javax.swing.JComponent; +import javax.swing.text.JTextComponent; +import javax.swing.text.BadLocationException; + +import com.artenum.rosetta.interfaces.core.CompletionItem; +import com.artenum.rosetta.interfaces.core.CompletionManager; + +import org.scilab.modules.completion.AbstractSciCompletionWindow; +import org.scilab.modules.completion.Completion; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; + +/** + * Scilab completion window main class + * @author Vincent COUVERT + * @author Calixte DENIZET + */ +public class SciNotesCompletionWindow extends AbstractSciCompletionWindow { + + private SciNotes editor; + private CompletionManager completionManager; + + /** + * Default constructor + * @param editor the editor + * @param completionManager the CompletionManager + */ + public SciNotesCompletionWindow(SciNotes editor, CompletionManager completionManager) { + this.editor = editor; + this.completionManager = completionManager; + } + + /** + * @return the JTextComponent where the CompletionWindow will be drawn + */ + public JTextComponent getTextComponent() { + return (JTextComponent) editor.getTextPane(); + } + + /** + * @return the list of the possibilities to complete + */ + public List<CompletionItem> getCompletionItems() { + return completionManager.getCompletionItems(); + } + + /** + * Set the parent component for the completion window + * @param component the parent component + * Caution, the component shouldn't be null otherwise the completion window + * will never get the focus + */ + public void setGraphicalContext(Component component) { + setFocusOut((JComponent) component); + super.setGraphicalContext(component); + } + + /** + * Make the completion window visible and update its content + * @param list list of items matching completion + * @param location position of the top left corner of the window + * @see com.artenum.rosetta.interfaces.ui.CompletionWindow#show(java.util.List, java.awt.Point) + */ + public void show(List<CompletionItem> list, Point location) { + currentCaretPosition = inputParsingManager.getCaretPosition(); + /* Display only in completion items list is not empty */ + if (list != null) { + /* If completion window size bigger than input command view size + put the window on the top of the current line */ + ScilabEditorPane first = editor.getTextPane(); + int height; + int value; + value = first.getScrollPane().getVerticalScrollBar().getValue(); + height = first.getScrollPane().getHeight(); + if (first.getOtherPaneInSplit() != null) { + getTextComponent().add(window); + } + if (window.getHeight() + location.y > value + height) { + try { + int ypos = first.modelToView(currentCaretPosition).height; + location.y = location.y - window.getHeight() - ypos; + } catch (BadLocationException e) { } + } + + model.updateData(list); + + /* Display completion window */ + window.setLocation(location); + window.setVisible(true); + + scrollPane.getViewport().setViewPosition(new Point(0, 0)); + + if (model.getSize() > 0) { + listUI.setSelectedIndex(0); + } + listUI.grabFocus(); + } + } + + /** + * Set the visibility status of the completion window + * @param status true if the window is visible (false else) + */ + public void setVisible(boolean status) { + window.setVisible(status); + if (!status) { + editor.getTextPane().grabFocus(); + } + } + + /** + * Add the completed word in the TextComponent + * @param position where to append the completed word + */ + public void addCompletedWord(int position) { + addCompletedWord(((CompletionItem) listUI.getSelectedValue()).getReturnValue(), position); + } + + /** + * Add the completed word in the TextComponent + * @param str the string to add + * @param position where to append the completed word + */ + public void addCompletedWord(String str, int position) { + String currentLine = inputParsingManager.getCommandLine(); + + String newLine = currentLine.substring(0, currentLine.length() - Completion.getPartLevel(currentLine).length()); + newLine += str; + inputParsingManager.reset(); + inputParsingManager.append(newLine); + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesContents.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesContents.java new file mode 100755 index 000000000..2fb2deaf2 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesContents.java @@ -0,0 +1,80 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2011 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +import javax.swing.JPanel; + +import org.scilab.modules.scinotes.SciNotes; + +/** + * Content pane for SciNotes. + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class SciNotesContents extends JPanel { + + private ScilabTabbedPane stp; + private Component bottom; + + /** + * Default constructor + * @param editor the editor where to put this pane + */ + public SciNotesContents(final SciNotes editor) { + super(new BorderLayout()); + stp = new ScilabTabbedPane(editor); + add(stp); + addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + if (editor.getTextPane() != null) { + editor.getTextPane().requestFocus(); + } + } + public void focusLost(FocusEvent e) { } + }); + } + + /** + * @return the tabbed pane used in this content pane + */ + public ScilabTabbedPane getScilabTabbedPane() { + return stp; + } + + /** + * @param comp the component to insert at the bottom of this panel + */ + public void insertBottomComponent(Component comp) { + if (comp == null) { + if (bottom != null) { + remove(bottom); + } + } else { + bottom = comp; + add(comp, BorderLayout.PAGE_END); + } + revalidate(); + } + + /** + * @return the component at the bottom + */ + public Component getBottom() { + return bottom; + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesMessages.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesMessages.java new file mode 100755 index 000000000..2bff7f087 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SciNotesMessages.java @@ -0,0 +1,346 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Bruno JOFRET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +//CHECKSTYLE:OFF + +package org.scilab.modules.scinotes.utils; + +import org.scilab.modules.localization.Messages; + +/** + * All messages used in SciNotes menus, dialogs, ... + * @author Bruno JOFRET + * @author Calixte DENIZET + */ +public class SciNotesMessages { + + public static final String DOTS = "..."; + public static final String QUOTE = "'"; + + public static final String SCILAB_EDITOR = Messages.gettext("SciNotes"); + public static final String ERROR_WITH_STRING = Messages.gettext("Error while reading the String"); + public static final String CORRUPTED_CONF_FILE = Messages.gettext("The configuration file has been corrupted and reset to default one."); + + public static final String INVALID_FILE = Messages.gettext("File not found: %s"); + public static final String IO_EXCEPTION = Messages.gettext("I/O error: %s"); + public static final String ASK_TO_RELOAD = Messages.gettext("The file %s has been modified by an other program. Reload it ?"); + + /** FILE MENU */ + public static final String FILE = Messages.gettext("File"); + public static final String NEW = Messages.gettext("New") + DOTS; + public static final String OPEN = Messages.gettext("Open") + DOTS; + public static final String OPEN_SOURCE_FILE_ON_KEYWORD = Messages.gettext("Open function source file") + DOTS; + public static final String OPEN_URL = Messages.gettext("Open URL") + DOTS; + public static final String SOURCE_OF = Messages.gettext("Source of '"); + public static final String RECENT_FILES = Messages.gettext("Recent Files"); + public static final String SAVE = Messages.gettext("Save"); + public static final String SAVE_AS = Messages.gettext("Save as") + DOTS; + public static final String OPEN_ERROR = Messages.gettext("The file could not be created, check the path"); + public static final String READONLY = Messages.gettext("The file is not writable so it is opened in read-only mode"); + public static final String NOTWRITABLE = Messages.gettext("You do not have the permissions to write this file"); + public static final String NOTREADABLE = Messages.gettext("You do not have the permissions to read this file"); + + /** + * "Save All" message + */ + public static final String SAVE_ALL = Messages.gettext("Save All"); + public static final String PAGE_SETUP = Messages.gettext("Page Setup") + DOTS; + public static final String PRINT_PREVIEW = Messages.gettext("Print Preview") + DOTS; + public static final String PRINT = Messages.gettext("Print") + DOTS; + public static final String EXPORTERROR = Messages.gettext("An error occurred when exporting the code using FOP"); + public static final String PRINTERERROR = Messages.gettext("An error occurred when printing"); + public static final String CLOSE = Messages.gettext("Close"); + public static final String CLOSEALL = Messages.gettext("Close All"); + public static final String CLOSEALLBUTTHIS = Messages.gettext("Close All But This"); + public static final String EXIT = Messages.gettext("Exit"); + public static final String QUESTION_MARK = Messages.gettext("?"); + + /** EDIT MENU */ + public static final String EDIT = Messages.gettext("Edit"); + public static final String UNDO = Messages.gettext("Undo"); + public static final String REDO = Messages.gettext("Redo"); + public static final String CUT = Messages.gettext("Cut"); + public static final String COPY = Messages.gettext("Copy"); + public static final String PASTE = Messages.gettext("Paste"); + public static final String SELECT_ALL = Messages.gettext("Select All"); + public static final String DELETE = Messages.gettext("Delete"); + + /** TOOLS MENU */ + public static final String TOOLS = Messages.gettext("Tools"); + public static final String COMMENT_SELECTION = Messages.gettext("Comment Selection"); + public static final String UNCOMMENT_SELECTION = Messages.gettext("Uncomment Selection"); + public static final String TABIFY_SELECTION = Messages.gettext("Shift Right"); + public static final String UNTABIFY_SELECTION = Messages.gettext("Shift Left"); + public static final String INDENT = Messages.gettext("Correct Indentation"); + public static final String HELP_ON_TYPING = Messages.gettext("Help on typing"); + public static final String GENERATE_HELP = Messages.gettext("Generate help from function"); + public static final String OPEN_TAB_IN_NEW_WINDOW = Messages.gettext("Clone tab in a new window"); + public static final String CCLOSE_TAB_IN_NEW_WINDOW = Messages.gettext("Clone and close tab in a new window"); + public static final String REMOVE_TRAILING_WHITE = Messages.gettext("Remove trailing whitespaces"); + + /** SEARCH MENU */ + public static final String SEARCH = Messages.gettext("Search"); + public static final String FIND_REPLACE = Messages.gettext("Find/Replace"); + public static final String FIND_NEXT = Messages.gettext("Find Next"); + public static final String FIND_PREVIOUS = Messages.gettext("Find Previous"); + public static final String GOTO_LINE = Messages.gettext("Goto line"); + + /** VIEW MENU */ + public static final String VIEW = Messages.gettext("View"); + public static final String SHOW_HIDE_TOOLBAR = Messages.gettext("Show/Hide ToolBar"); + public static final String HIGHLIGHT_CURRENT_LINE = Messages.gettext("Highlight current line"); + public static final String WORD_WRAP = Messages.gettext("Word Wrap"); + public static final String LINE_NUMBERS_WHEREAMI = Messages.gettext("Whereami Line Numbering"); + public static final String LINE_NUMBERS_NOWHEREAMI = Messages.gettext("Normal Line Numbering"); + public static final String NO_LINE_NUMBERS = Messages.gettext("No Line Numbering"); + + public static final String SET_COLORS = Messages.gettext("Set Colors") + DOTS; + public static final String SET_FONT = Messages.gettext("Set Font") + DOTS; + public static final String RESET_DEFAULT_FONT = Messages.gettext("Reset default font"); + + public static final String SPLIT_HORIZONTALLY = Messages.gettext("Split horizontally"); + public static final String SPLIT_VERTICALLY = Messages.gettext("Split vertically"); + public static final String NO_SPLIT = Messages.gettext("No split"); + + /** DOCUMENT MENU */ + public static final String DOCUMENT = Messages.gettext("Document"); + public static final String SYNTAX_TYPE = Messages.gettext("Syntax Type"); + public static final String SCILAB_STYLE = Messages.gettext("Scilab"); + public static final String PLAIN_TEXT_STYLE = "Plain Text"; + public static final String XML_STYLE = "XML"; + public static final String ENCODING_TYPE = Messages.gettext("Encoding"); + public static final String COLORIZE = Messages.gettext("Colorize"); + public static final String AUTO_INDENT = Messages.gettext("Enable Auto Reformat"); + public static final String EOL_TYPE = Messages.gettext("Line Endings"); + public static final String EOL_AUT0 = Messages.gettext("Auto (Default)"); + public static final String EOL_WINDOWS = Messages.gettext("Windows/DOS (CR + LF)"); + public static final String EOL_MACOS = Messages.gettext("Mac Classic (CR)"); + public static final String EOL_LINUX = Messages.gettext("Unix (LF)"); + + /** EXECUTE MENU */ + public static final String EXECUTE = Messages.gettext("Execute"); + public static final String LOAD_INTO_SCILAB = Messages.gettext("Load Into Scilab"); + public static final String EVALUATE_SELECTION = Messages.gettext("Evaluate Selection"); + public static final String EVALUATE_FROM_BEGINNING = Messages.gettext("Evaluate from beginning..."); + public static final String EXECUTE_FILE_INTO_SCILAB = Messages.gettext("Execute File Into Scilab"); + + /** HELP MENU */ + public static final String HELP = Messages.gettext("SciNotes help") + DOTS; + public static final String HELP_ON_KEYWORD = Messages.gettext("Help on the current keyword"); + public static final String HELP_ON_SELECTED = Messages.gettext("Help on the selected text"); + public static final String HELP_ON_FOO = Messages.gettext("Help on selected text or keyword"); + public static final String HELP_ABOUT = Messages.gettext("Help about '"); + public static final String ABOUT = Messages.gettext("About") + DOTS; + public static final String SCINOTES_VERSION = Messages.gettext("SciNotes"); + + /** FIND/REPLACE DIALOG */ + public static final String FIND = Messages.gettext("Find:"); + public static final String FIND_BUTTON = Messages.gettext("Find"); + public static final String REPLACE_FIND = Messages.gettext("Replace/Find"); + public static final String REPLACE_WITH = Messages.gettext("Replace With :"); + public static final String DIRECTION = Messages.gettext("Direction"); + public static final String FORWARD = Messages.gettext("Forward"); + public static final String BACKWARD = Messages.gettext("Backward"); + public static final String SCOPE = Messages.gettext("Scope"); + public static final String ALL = Messages.gettext("All"); + public static final String SELECTED_LINES = Messages.gettext("Selected lines"); + public static final String SELECT_FROM_CARET = Messages.gettext("Select from caret"); + public static final String OPTIONS = Messages.gettext("Options"); + public static final String CASE_SENSITIVE = Messages.gettext("Case sensitive"); + public static final String CIRCULAR_SEARCH = Messages.gettext("Circular search"); + public static final String RESTART_FROM_BEGINNING = Messages.gettext("Restart the search from the beginning"); + public static final String WHOLE_WORD = Messages.gettext("Whole word"); + public static final String REGULAR_EXPRESSIONS = Messages.gettext("Regular expressions"); + public static final String REPLACE = Messages.gettext("Replace"); + public static final String REPLACE_ALL = Messages.gettext("Replace All"); + public static final String INVALID_REGEXP = Messages.gettext("Invalid regular expression : %s"); + public static final String PASSED_END_OF_DOCUMENT = Messages.gettext("You have passed the end of the document"); + public static final String PASSED_BEGIN_OF_DOCUMENT = Messages.gettext("You have passed the beginning of the document"); + public static final String END_OF_DOCUMENT = Messages.gettext("You have reached the end of the document"); + public static final String BEGIN_OF_DOCUMENT = Messages.gettext("You have reached the beginning of the document"); + public static final String STRING_NOT_FOUND = Messages.gettext("String %s not found"); + + public static final String FILE_DOESNT_EXIST = Messages.gettext("The file %s does not exist. Do you want to create it?"); + public static final String CLOSE_TAB_TIP = Messages.gettext("close this tab"); + public static final String THIS_FILE = Messages.gettext("This file"); + public static final String MODIFIED = Messages.gettext("The file %s has been modified since last save. Save it?"); + public static final String EXTERNAL_MODIFICATION = Messages.gettext("The file %s has been modified by another program ! Overwrite it ?"); + public static final String EXTERNAL_MODIFICATION_INFO = Messages.gettext("Warning: the file has been modified by another program !"); + public static final String RELOAD = Messages.gettext("Reload"); + public static final String OVERWRITE = Messages.gettext("Overwrite"); + public static final String IGNORE = Messages.gettext("Ignore"); + public static final String REPLACE_FILE_TITLE = Messages.gettext("Replace File?"); + public static final String FILE_ALREADY_EXIST = Messages.gettext("File already exists"); + public static final String UNTITLED = Messages.gettext("Untitled "); + public static final String OK = Messages.gettext("Ok"); + public static final String APPLYREINDENT = Messages.gettext("Apply & Reindent"); + public static final String CANCEL = Messages.gettext("Cancel"); + public static final String DEFAULT = Messages.gettext("Default"); + public static final String NEXT_TAB = Messages.gettext("Next tab"); + public static final String PREVIOUS_TAB = Messages.gettext("Previous tab"); + public static final String EXECUTE_WARNING = Messages.gettext("You need to save your modifications before executing this file into Scilab."); + public static final String BIG_FILE_WARNING = Messages.gettext("This file is very long. \"Execute File Into Scilab\" could be better.\nAre you sure to continue ?"); + + + public static final String ENTER_LINE_NUMBER = Messages.gettext("Enter line number"); + public static final String BINARY_FILE = Messages.gettext("This file is a binary, saving it will result in a corrupt file."); + + /* Status bar messages */ + public static final String LOADING = Messages.gettext("Loading") + DOTS; + public static final String COLORIZATION_CANCELED = Messages.gettext("Colorization canceled"); + public static final String BINARY_FILE_MODE = Messages.gettext("Binary file: read-only mode"); + public static final String READ_ONLY_MODE = Messages.gettext("Read-only mode"); + public static final String CLICKABLE_URL = Messages.gettext("Press CTRL and move the mouse over the link to activate it"); + public static final String OPENURL = Messages.gettext("Open in the navigator the URL "); + public static final String MAILTO = Messages.gettext("Mail to "); + public static final String OPENSOURCE = Messages.gettext("Open the source of the macro "); + public static final String SHOWSOURCE = Messages.gettext("Show the definition of the macro "); + public static final String POSFUN_IN_DOC = Messages.gettext("Line %s, Column %s. Function '%s' at Line %s."); + public static final String UNKNOWN_FUNCTION = Messages.gettext("Unknown function"); + public static final String POS_IN_DOC = Messages.gettext("Line %s, Column %s."); + + /* About box */ + public static final String VERSION = Messages.gettext("SciNotes") + " 1.1"; + public static final String COPYRIGHT = Messages.gettext("Copyright (c)") + " 2009-2012"; + + public static final String SCINOTES_ERROR = Messages.gettext("SciNotes error"); + public static final String COULD_NOT_SAVE_FILE = Messages.gettext("The file could not be saved."); + public static final String COULD_NOT_CONVERT_FILE = Messages.gettext("The file could not be converted."); + public static final String CANNOT_LOAD_DIRECTORY = Messages.gettext("%s is a directory."); + public static final String MODIFICATIONS_WILL_BE_LOST = Messages.gettext("Your modifications will be lost, change encoding anyway?"); + public static final String CONTINUE = Messages.gettext("Continue ?"); + public static final String CANNOT_LOAD_COLORIZE = Messages.gettext("Cannot load \"scinotesConfiguration.xml\""); + + public static final String COULD_NOT_FIND_CONSOLE = Messages.gettext("Could not find the console nor the InterpreterManagement."); + public static final String COULD_NOT_FIND_TMPFILE = Messages.gettext("Could not find the temporary file."); + public static final String NO_TEXT_SELECTED = Messages.gettext("No text selected."); + public static final String NO_TEXT_TO_EXECUTE = Messages.gettext("No text to execute."); + public static final String COMPLETE = Messages.gettext("Complete"); + public static final String EDIT_SELECTION = Messages.gettext("Copy selection in a new tab"); + + public static final String DIFFERENT_ENCODINGS = Messages.gettext("The file encoding is actually %s and it will be saved in using %s. Continue ?"); + public static final String DIFFERENT_ENCODINGS_TITLE = Messages.gettext("Encoding problems"); + public static final String CANNOT_GUESS_ENCODING = Messages.gettext("Cannot guess the file encoding."); + + public static final String AUTOSAVE_ERROR = Messages.gettext("Cannot save the file %s... stop the backup process"); + public static final String AUTOSAVE_FINISHED = Messages.gettext("Backup finished..."); + public static final String NO_EXISTING_DIR = Messages.gettext("The directory %s does not exist. Do you want to create it?"); + public static final String UNABLE_TO_CREATE_DIR = Messages.gettext("The directory %s cannot be created. Please check your access rights."); + public static final String NOT_WRITABLE_DIR = Messages.gettext("Impossible to write a file in %s. Please check your access rights."); + public static final String NOT_A_DIR = Messages.gettext("Invalid directory name: %s."); + public static final String AUTOSAVE = Messages.gettext("SciNotes autosave"); + + public static final String OCCURENCES_FOUND = Messages.gettext("%s occurences found."); + + /** + * "Change Colors" message + */ + public static final String CHANGE_COLORS = Messages.gettext("Change Colors"); + + /** + * "Change Color" message + */ + public static final String CARET_COLOR = Messages.gettext("Cursor Color"); + public static final String BGCOLOR = Messages.gettext("Background Color"); + public static final String CHANGE_COLOR = Messages.gettext("Change Color"); + public static final String ITALIC = Messages.gettext("Italic"); + public static final String STRIKETHROUGH = Messages.gettext("Strike Through"); + public static final String PREVIEW = Messages.gettext("Preview"); + public static final String UNDERLINE = Messages.gettext("Underline"); + public static final String SETTINGS = Messages.gettext("Settings"); + public static final String COLOR = Messages.gettext("Color"); + public static final String BOLD = Messages.gettext("Bold"); + + /** + * Navigator labels + */ + public static final String CODE_NAVIGATOR = Messages.gettext("Code Navigator"); + public static final String ABSOLUTE = Messages.gettext("Absolute"); + public static final String RELATIVE = Messages.gettext("Relative"); + public static final String GO_TO_LINE = Messages.gettext("Go to line: "); + public static final String NUMEROTATION = Messages.gettext("Numeration"); + public static final String ALPHABETIC_ORDER = Messages.gettext("Alphabetic order"); + public static final String NATURAL_ORDER = Messages.gettext("Natural order"); + public static final String ORDER = Messages.gettext("Order"); + public static final String FUNCTIONS = Messages.gettext("Functions"); + public static final String ANCHORS = Messages.gettext("Anchors"); + + /** + * Anchor + */ + public static final String ANCHOR_NAME = Messages.gettext("Anchor's name: "); + public static final String SET_ANCHOR = Messages.gettext("Set an anchor"); + public static final String ANCHOR = Messages.gettext("Anchor: "); + + /** + * Open source + */ + public static final String OPEN_SOURCE_FILE_OF = Messages.gettext("Open source file of the function:"); + public static final String OPEN_SOURCE = Messages.gettext("Open source") + DOTS; + + /** + * Exit confirm message + */ + public static final String EXIT_CONFIRM = Messages.gettext("Are you sure that you want to close SciNotes ?"); + + /** + * Restore previous session's files query message + */ + public static final String RESTORE_FILES_QUERY = Messages.gettext("Restore files from your last SciNotes session ?"); + public static final String RESTORE_FILES_TITLE = Messages.gettext("Restore the last sessions"); + + /** + * Tabulations configuration + */ + public static final String CONFIGTAB = Messages.gettext("Configure Tabulation"); + public static final String TABSTYLE = Messages.gettext("Tab style"); + public static final String TABUSEWHITES = Messages.gettext("Use spaces"); + public static final String TABLENGTH = Messages.gettext("Length"); + public static final String TABREPRESENTATION = Messages.gettext("Tab representation"); + public static final String TABHRULE = Messages.gettext("Horizontal rule"); + public static final String TABVRULE = Messages.gettext("Vertical rule"); + public static final String TABDOUBLECHEVRONS = Messages.gettext("Double chevrons"); + + public static final String COPYFULLFILEPATH = Messages.gettext("Copy full path"); + + /** + * Incremental search + */ + public static final String EXACT = Messages.gettext("Exact"); + + /** + * Find in files + */ + public static final String SEARCHFILES = Messages.gettext("Search Files..."); + public static final String SEARCHINFILES = Messages.gettext("Search in Files..."); + public static final String MATCHES = Messages.gettext("<html>%s <i>(%s matches)</i></html>"); + public static final String MATCH = Messages.gettext("<html>%s <i>(%s match)</i></html>"); + public static final String ELAPSEDTIME = Messages.gettext("Elapsed time: %s sec."); + public static final String BASEDIRECTORY = Messages.gettext("Base directory:"); + public static final String RECURSIVE = Messages.gettext("Recursive"); + public static final String FILEPATTERN = Messages.gettext("File pattern"); + public static final String FILEPATTERNEXP = Messages.gettext("(* for any string and ? for any character)"); + public static final String BASEDIREXP = Messages.gettext("(~ for user home dir. and SCI for Scilab base dir.)"); + public static final String WORDPATTERN = Messages.gettext("Word pattern"); + public static final String FILELINEBYLINE = Messages.gettext("Read file line by line"); + public static final String CHOOSEDIR = Messages.gettext("Choose..."); + public static final String STOPBUTTON = Messages.gettext("Stop"); + public static final String REGEXPATTERN = Messages.gettext("Regex"); + public static final String WORD = Messages.gettext("Word"); + public static final String WORDCASESENSITIVE = Messages.gettext("Case-sensitivity (Word)"); + public static final String FILECASESENSITIVE = Messages.gettext("Case-sensitivity (File name)"); + public static final String RECURSIVESEARCH = Messages.gettext("Recursive search"); + public static final String LINEBYLINE = Messages.gettext("Line by line"); + public static final String WORDREGEX = Messages.gettext("Regular expression (Word)"); + public static final String CHOOSEBASEDIR = Messages.gettext("Choose the search base directory"); +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ScilabScrollPane.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ScilabScrollPane.java new file mode 100755 index 000000000..183ce99c1 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ScilabScrollPane.java @@ -0,0 +1,130 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2011 - DIGITEO - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.lang.reflect.Field; +import java.util.List; + +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.plaf.ScrollBarUI; +import javax.swing.plaf.basic.BasicScrollBarUI; + +/** + * A ScrollPane where the vertical scrollbar can contains marks to indicate particular positions in the document. + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class ScilabScrollPane extends JScrollPane { + + private static final Color MARKCOLOR = new Color(229, 192, 0); + private List<Rectangle> marks; + + /** + * Default constructor + * @param view the view to put in the scrollpane + */ + public ScilabScrollPane(Component view) { + super(view); + } + + /** + * {@inheritDoc} + */ + public JScrollBar createVerticalScrollBar() { + return new ScilabVerticalScrollBar(); + } + + /** + * Put marks in the vertical scrollbar + * @param marks a list of the rectangle corresponding to the line in the document + */ + public void putMarks(List<Rectangle> marks) { + this.marks = marks; + getVerticalScrollBar().repaint(); + } + + /** + * Remove all the marks + */ + public void removeMarks() { + this.marks = null; + getVerticalScrollBar().repaint(); + } + + /** + * {@inheritDoc} + */ + protected class ScilabVerticalScrollBar extends ScrollBar { + + private Field trackRect; + private Field thumbRect; + private ScrollBarUI ui; + + /** + * Default constructor + */ + public ScilabVerticalScrollBar() { + super(JScrollBar.VERTICAL); + ui = getUI(); + initFields(); + } + + /** + * Init the protected fields in BasicScrollBarUI. These fields are used to get the dimension of the thumb and of the track. + */ + private void initFields() { + if (ui instanceof BasicScrollBarUI) { + try { + trackRect = BasicScrollBarUI.class.getDeclaredField("trackRect"); + trackRect.setAccessible(true); + thumbRect = BasicScrollBarUI.class.getDeclaredField("thumbRect"); + thumbRect.setAccessible(true); + } catch (Exception e) { } + } + } + + /** + * {@inheritDoc} + */ + public void paint(Graphics g) { + super.paint(g); + g.setColor(MARKCOLOR); + ScrollBarUI ui = getUI(); + if (this.ui != ui) { + this.ui = ui; + initFields(); + } + if (ui instanceof BasicScrollBarUI && trackRect != null && thumbRect != null) { + BasicScrollBarUI basicUI = (BasicScrollBarUI) ui; + try { + Rectangle track = (Rectangle) trackRect.get(basicUI); + Rectangle thumb = (Rectangle) thumbRect.get(basicUI); + double ratio = (double) track.height / (double) getMaximum(); + if (marks != null) { + for (Rectangle mark : marks) { + Rectangle r = new Rectangle(track.x, track.y + (int) ((mark.y + mark.height) * ratio), track.width, 2); + if (!thumb.contains(r)) { + g.fillRect(r.x, r.y, r.width, r.height); + } + } + } + } catch (Exception e) { } + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ScilabTabbedPane.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ScilabTabbedPane.java new file mode 100755 index 000000000..22eb202d3 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/ScilabTabbedPane.java @@ -0,0 +1,506 @@ +/* + * Scilab (http://www.scilab.org/) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Component; +import java.awt.Container; +import java.awt.DefaultFocusTraversalPolicy; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JRootPane; +import javax.swing.JTabbedPane; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; + +import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem; +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.utils.ClosingOperationsManager; + +import org.scilab.modules.scinotes.EditorComponent; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.actions.CloseAction; +import org.scilab.modules.scinotes.actions.CloseAllButThisAction; +import org.scilab.modules.scinotes.actions.RestoreOpenedFilesAction; +import org.scilab.modules.scinotes.actions.SaveAction; + +/** + * Class for a tabbedpane with close-button + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class ScilabTabbedPane extends JTabbedPane implements DragGestureListener, + DragSourceListener, + DropTargetListener, + Transferable { + + private static final ImageIcon CLOSEICON = new ImageIcon(System.getenv("SCI") + "/modules/gui/images/icons/close-tab.png"); + private static final ImageIcon CLOSEONICON = new ImageIcon(System.getenv("SCI") + "/modules/gui/images/icons/close-tab-on.png"); + private static final int BUTTONSIZE = 18; + + private static DataFlavor DATAFLAVOR; + private static ScilabTabbedPane currentWhenDragged; + + static { + try { + DATAFLAVOR = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + ScilabTabbedPane.class.getName()); + } catch (ClassNotFoundException e) { } + } + + private SciNotes editor; + private int draggedIndex; + + /** + * Constructor + * @param editor the editor + */ + public ScilabTabbedPane(SciNotes editor) { + super(); + this.editor = editor; + setFocusTraversalPolicy(new java.awt.DefaultFocusTraversalPolicy() { + public Component getComponentAfter(Container aContainer, Component aComponent) { + if (aComponent instanceof ScilabEditorPane) { + return aComponent; + } + return super.getComponentAfter(aContainer, aComponent); + } + }); + + setFocusCycleRoot(true); + + setComponentPopupMenu(createPopupMenu()); + DragSource dragsource = DragSource.getDefaultDragSource(); + dragsource.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this); + DropTarget droptarget = new DropTarget(this, this); + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 1 && SwingUtilities.isMiddleMouseButton(e)) { + int index = indexAtLocation(e.getX(), e.getY()); + ((CloseTabButton) getTabComponentAt(index)).closeTab(); + e.consume(); + } + } + }); + } + + /** + * {@inheritDoc} + */ + public void insertTab(String title, Icon icon, Component component, String tip, int index) { + super.insertTab(title, icon, component, tip, index); + setTabComponentAt(index, new CloseTabButton(title)); + } + + /** + * @param index the index of the tab + * @return the title of the tab + */ + public String getScilabTitleAt(int index) { + CloseTabButton tab = (CloseTabButton) getTabComponentAt(index); + if (tab != null) { + return tab.getText(); + } + + return ""; + } + + /** + * {@inheritDoc} + */ + public String getTitleAt(int index) { + return ""; + } + + /** + * {@inheritDoc} + */ + public void setTitleAt(int index, String title) { + CloseTabButton tab = (CloseTabButton) getTabComponentAt(index); + if (tab != null) { + tab.setText(title); + } + } + + /** + * Implements getTransferData in Transferable + * @param flavor to get + * @return the object to transfer + * @throws UnsupportedFlavorException for an unknown flavor + */ + public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { + if (!flavor.equals(DATAFLAVOR)) { + throw new UnsupportedFlavorException(flavor); + } + + return this; + } + + /** + * Implements getTransferDataFlavors in Transferable + * @return the supported flavors + */ + public DataFlavor[] getTransferDataFlavors() { + return new DataFlavor[] {DATAFLAVOR}; + } + + /** + * Implements isDataFlavorSupported in Transferable + * @param flavor to support + * @return true if the flavor is supported + */ + public boolean isDataFlavorSupported(DataFlavor flavor) { + return flavor.equals(DATAFLAVOR); + } + + /** + * Interface DropTargetListener + * {@inheritDoc} + */ + public void dragEnter(DropTargetDragEvent dtde) { + if (dtde.isDataFlavorSupported(DATAFLAVOR)) { + dtde.acceptDrag(DnDConstants.ACTION_MOVE); + Component c = dtde.getDropTargetContext().getComponent(); + if (c instanceof ScilabTabbedPane) { + currentWhenDragged = (ScilabTabbedPane) c; + } + } else { + dtde.rejectDrag(); + } + } + + /** + * Interface DropTargetListener + * {@inheritDoc} + */ + public void dragOver(DropTargetDragEvent dtde) { + if (dtde.isDataFlavorSupported(DATAFLAVOR)) { + dtde.acceptDrag(DnDConstants.ACTION_MOVE); + } else { + dtde.rejectDrag(); + } + } + + /** + * Interface DropTargetListener + * {@inheritDoc} + */ + public void drop(DropTargetDropEvent dtde) { + if (!dtde.isDataFlavorSupported(DATAFLAVOR) || dtde.getSourceActions() != DnDConstants.ACTION_MOVE) { + dtde.rejectDrop(); + } else { + try { + ScilabTabbedPane tabbedPane = (ScilabTabbedPane) dtde.getTransferable().getTransferData(DATAFLAVOR); + int index = indexAtLocation(dtde.getLocation().x, dtde.getLocation().y); + if (tabbedPane == this && (index == tabbedPane.draggedIndex || getTabCount() == 1)) { + dtde.rejectDrop(); + } else { + Component c = tabbedPane.getComponentAt(tabbedPane.draggedIndex); + String title = tabbedPane.getScilabTitleAt(tabbedPane.draggedIndex); + ConfigSciNotesManager.removeFromOpenFiles(tabbedPane.editor, tabbedPane.editor.getTextPane(tabbedPane.draggedIndex)); + if (tabbedPane.editor.getNavigator() != null) { + tabbedPane.editor.getNavigator().removePane(tabbedPane.editor.getTextPane(tabbedPane.draggedIndex)); + } + tabbedPane.remove(c); + if (tabbedPane.getTabCount() == 0) { + SciNotes.closeEditor(tabbedPane.editor); + } + if (index == -1) { + index = getTabCount(); + } + + insertTab(title, null, c, null, index); + ScilabEditorPane sep = editor.getTextPane(indexOfComponent(c)); + + if (tabbedPane != this) { + sep.setEditor(editor); + editor.initInputMap(sep); + } + + if (sep.getName() != null) { + ConfigSciNotesManager.saveToOpenFiles(sep.getName(), editor, sep, index); + } else if (tabbedPane != this) { + int n = editor.getNumberForEmptyTab(); + sep.setShortName(SciNotesMessages.UNTITLED + n); + sep.setTitle(SciNotesMessages.UNTITLED + n); + setTitleAt(index, SciNotesMessages.UNTITLED + n); + editor.setTitle(sep.getTitle()); + } + + setSelectedIndex(index); + editor.updateTabTitle(); + + dtde.acceptDrop(DnDConstants.ACTION_MOVE); + } + } catch (IOException e) { + dtde.rejectDrop(); + } catch (UnsupportedFlavorException e) { + dtde.rejectDrop(); + } + } + } + + /** + * Interface DropTargetListener + * {@inheritDoc} + */ + public void dropActionChanged(DropTargetDragEvent dtde) { } + + /** + * Interface DropTargetListener + * {@inheritDoc} + */ + public void dragExit(DropTargetEvent dte) { } + + /** + * Interface DragSourceListener + * {@inheritDoc} + */ + public void dragDropEnd(DragSourceDropEvent dsde) { + Component c = null; + for (SciNotes sn : SciNotes.getSciNotesList()) { + Point point = new Point(dsde.getLocation()); + SwingUtilities.convertPointFromScreen(point, sn); + c = SwingUtilities.getDeepestComponentAt(sn, (int) point.getX(), (int) point.getY()); + if (c != null) { + break; + } + } + + if (c == null) { + SciNotes.cloneAndCloseCurrentTab(editor, true, dsde.getX(), dsde.getY()); + } + } + + /** + * Interface DragSourceListener + * {@inheritDoc} + */ + public void dragExit(DragSourceEvent dse) { } + + /** + * Interface DragSourceListener + * {@inheritDoc} + */ + public void dragOver(DragSourceDragEvent dsde) { + Point pt = new Point(dsde.getX(), dsde.getY()); + JRootPane rootpane = (JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class, currentWhenDragged); + + if (rootpane != null) { + SwingUtilities.convertPointFromScreen(pt, rootpane); + Component c = SwingUtilities.getDeepestComponentAt(rootpane, pt.x, pt.y); + + if (c != null && !(c instanceof ScilabEditorPane) && !(c instanceof ScilabTabbedPane)) { + c = SwingUtilities.getAncestorOfClass(ScilabTabbedPane.class, c); + } + } + } + + /** + * Interface DragSourceListener + * {@inheritDoc} + */ + public void dragEnter(DragSourceDragEvent dsde) { } + + /** + * Interface DragSourceListener + * {@inheritDoc} + */ + public void dropActionChanged(DragSourceDragEvent dsde) { } + + /** + * Interface DragGestureListener + * {@inheritDoc} + */ + public void dragGestureRecognized(DragGestureEvent dge) { + InputEvent inputEvent = dge.getTriggerEvent(); + if (inputEvent instanceof MouseEvent) { + MouseEvent mouseEvent = (MouseEvent) inputEvent; + int index = indexAtLocation(mouseEvent.getX(), mouseEvent.getY()); + if (index == -1 || (getComponentAt(index) instanceof EditorComponent)) { + currentWhenDragged = this; + + if (index != -1) { + draggedIndex = index; + dge.startDrag(DragSource.DefaultMoveDrop, this, this); + } + } + } + } + + /** + * Create a popupmenu for the tabs + * @return the created popupmenu + */ + private JPopupMenu createPopupMenu() { + JPopupMenu popup = new JPopupMenu() { + public void show(Component invoker, int x, int y) { + int index = ScilabTabbedPane.this.indexAtLocation(x, y); + ScilabTabbedPane.this.setSelectedIndex(index); + super.show(invoker, x, y); + } + }; + + Map<String, KeyStroke> map = SciNotes.getActionKeys(); + + SwingScilabMenuItem menuItem; + menuItem = (SwingScilabMenuItem) SaveAction.createMenu(SciNotesMessages.SAVE, editor, map.get("scinotes-save")).getAsSimpleMenuItem(); + popup.add(menuItem); + + menuItem = (SwingScilabMenuItem) CloseAction.createMenu(SciNotesMessages.CLOSE, editor, map.get("scinotes-close")).getAsSimpleMenuItem(); + popup.add(menuItem); + + menuItem = (SwingScilabMenuItem) CloseAllButThisAction.createMenu(SciNotesMessages.CLOSEALLBUTTHIS, editor, map.get("scinotes-close-all-but")).getAsSimpleMenuItem(); + popup.add(menuItem); + + popup.addSeparator(); + + final JMenuItem menuitem = new JMenuItem(SciNotesMessages.COPYFULLFILEPATH); + menuitem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent actionEvent) { + if (editor.getTextPane() != null) { + StringSelection sel = new StringSelection(editor.getTextPane().getName()); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(sel, sel); + } + } + }); + menuitem.addPropertyChangeListener(new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent e) { + if (editor.getTextPane() != null) { + String name = editor.getTextPane().getName(); + menuitem.setEnabled(name != null && !name.isEmpty()); + } + } + }); + popup.add(menuitem); + + return popup; + } + + /** + * Inner class to have a label and a button + */ + class CloseTabButton extends JPanel { + + private JLabel label; + + /** + * Constructor + * @param title the title of the tab + */ + public CloseTabButton(String title) { + super(new FlowLayout(FlowLayout.LEFT, 0, 0)); + setOpaque(false); + label = new JLabel(title); + add(label); + add(new JLabel(" ")); + add(new CloseButton()); + } + + /** + * @param text the text for the tab + */ + public void setText(String text) { + label.setText(text); + } + + /** + * @return the text of the tab + */ + public String getText() { + return label.getText(); + } + + public void closeTab() { + ScilabEditorPane sep = editor.getTextPane(editor.getTabPane().indexOfTabComponent(this)); + if (sep != null) { + String name = sep.getName(); + editor.closeTabAt(editor.getTabPane().indexOfTabComponent(this)); + if (getTabCount() == 0) { + if (name != null) { + editor.addEmptyTab(); + } else { + SciNotes.closeEditor(editor); + } + } + } else if (editor.getTabPane().getTabComponentAt(editor.getTabPane().indexOfTabComponent(this)) != null) { + editor.getTabPane().remove(editor.getTabPane().indexOfTabComponent(this)); + if (editor.getTabPane().getTabCount() == 0) { + editor.addEmptyTab(); + } + RestoreOpenedFilesAction.restoreEnabledComponents(editor); + } + } + + /** + * Inner class for the close-button + */ + class CloseButton extends JButton { + + /** + * Constructor + */ + CloseButton() { + super(CLOSEICON); + setFocusable(false); + setContentAreaFilled(true); + setOpaque(false); + setRolloverEnabled(true); + setRolloverIcon(CLOSEONICON); + setBorderPainted(false); + setPreferredSize(new Dimension(BUTTONSIZE, BUTTONSIZE)); + addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + closeTab(); + } + }); + } + } + } +} diff --git a/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SearchFile.java b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SearchFile.java new file mode 100755 index 000000000..ffccb3791 --- /dev/null +++ b/modules/scinotes/src/java/org/scilab/modules/scinotes/utils/SearchFile.java @@ -0,0 +1,632 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ + +package org.scilab.modules.scinotes.utils; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.regex.Pattern; + +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; + +import org.flexdock.docking.event.DockingEvent; +import org.scilab.modules.commons.ScilabCommons; +import org.scilab.modules.commons.ScilabConstants; +import org.scilab.modules.commons.xml.ScilabXMLUtilities; +import org.scilab.modules.gui.bridge.menuitem.SwingScilabMenuItem; +import org.scilab.modules.gui.bridge.tab.SwingScilabDockablePanel; +import org.scilab.modules.gui.bridge.window.SwingScilabWindow; +import org.scilab.modules.gui.events.callback.CommonCallBack; +import org.scilab.modules.gui.menu.Menu; +import org.scilab.modules.gui.menu.ScilabMenu; +import org.scilab.modules.gui.menubar.MenuBar; +import org.scilab.modules.gui.menubar.ScilabMenuBar; +import org.scilab.modules.gui.menuitem.MenuItem; +import org.scilab.modules.gui.menuitem.ScilabMenuItem; +import org.scilab.modules.gui.tab.SimpleTab; +import org.scilab.modules.gui.tabfactory.ScilabTabFactory; +import org.scilab.modules.gui.textbox.ScilabTextBox; +import org.scilab.modules.gui.textbox.TextBox; +import org.scilab.modules.gui.toolbar.ToolBar; +import org.scilab.modules.gui.utils.ClosingOperationsManager; +import org.scilab.modules.gui.utils.WindowsConfigurationManager; +import org.scilab.modules.scinotes.SciNotes; +import org.scilab.modules.scinotes.SciNotesGUI; +import org.scilab.modules.scinotes.ScilabEditorPane; +import org.scilab.modules.scinotes.SearchManager; +import org.scilab.modules.scinotes.tabfactory.SearchInFilesTabFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * Class SearchFile: open a window with a JTree to show the results of a search in files. + * @author Calixte DENIZET + */ +@SuppressWarnings(value = { "serial" }) +public class SearchFile extends SwingScilabDockablePanel { + + public static final String SEARCHDONE = "SearchFile.SearchDone"; + + static { + ScilabTabFactory.getInstance().addTabFactory(SearchInFilesTabFactory.getInstance()); + } + + private SwingScilabWindow parentWindow; + private SciNotes editor; + private MyBackgroundSearch mySearch; + private JTree tree; + + /** + * Default constructor + * @param editor the editor where to open a file + * @param uuid the tab uuid + */ + public SearchFile(SciNotes editor, String uuid) { + super(SciNotesMessages.SEARCHINFILES, uuid == null ? UUID.randomUUID().toString() : uuid); + this.editor = editor; + editor.addSearchInFiles(this); + ConfigSciNotesManager.saveSearchInFilesState(editor.getPersistentId(), getPersistentId()); + initTab(); + restoreSearchFile(); + WindowsConfigurationManager.restorationFinished(this); + } + + /** + * Default constructor + * @param editor the editor where to open a file + */ + public SearchFile(SciNotes editor) { + this(editor, null); + } + + /** + * Set the parent window + */ + public void setParentWindow() { + parentWindow = SwingScilabWindow.createWindow(true); + parentWindow.addTab(this); + parentWindow.setVisible(true); + } + + /** + * Get the parent window for this tab + * @return the parent window + */ + public SwingScilabWindow getParentWindow() { + return this.parentWindow; + } + + /** + * {@inheritDoc} + */ + public SimpleTab getAsSimpleTab() { + return this; + } + + /** + * {@inheritDoc} + */ + public void addInfoBar(TextBox infoBarToAdd) { + setInfoBar(infoBarToAdd); + } + + /** + * {@inheritDoc} + */ + public void addMenuBar(MenuBar menuBarToAdd) { + setMenuBar(menuBarToAdd); + } + + /** + * {@inheritDoc} + */ + public void addToolBar(ToolBar toolBarToAdd) { + setToolBar(toolBarToAdd); + } + + /** + * {@inheritDoc} + */ + @Override + public void dockingComplete(DockingEvent evt) { + super.dockingComplete(evt); + changeToolBar(); + } + + /** + * Try to add a SciNotes toolbar + */ + public void changeToolBar() { + SwingScilabWindow win = (SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this); + Set<SwingScilabDockablePanel> set = win.getDockingPort().getDockables(); + for (SwingScilabDockablePanel tab : set) { + if (tab == editor) { + addToolBar(editor.getToolBar()); + break; + } + } + } + + /** + * Close the current window + */ + public void closeSearchInFiles() { + saveSearchFile(); + editor.removeSearchInFiles(); + editor = null; + parentWindow = null; + } + + /** + * {@inheritDoc} + */ + @Override + public void undockingComplete(DockingEvent evt) { + super.undockingComplete(evt); + addToolBar(null); + } + + /** + * Set a MyBackgroundSearch to this SearchFile + * @param search a MyBackgroundSearch + */ + public void setMyBackgroundSearch(MyBackgroundSearch search) { + mySearch = search; + } + + private void saveSearchFile() { + if (mySearch != null) { + try { + FileWriter fwriter = new FileWriter(ScilabConstants.SCIHOME.toString() + File.separator + getPersistentId() + ".xml"); + BufferedWriter buffer = new BufferedWriter(fwriter); + buffer.append("<SearchResults editor=\"" + editor.getUUID() + "\""); + buffer.append(" base=\"" + mySearch.base + "\""); + buffer.append(" recursive=\"" + mySearch.recursive + "\""); + buffer.append(" ignoreCR=\"" + mySearch.ignoreCR + "\""); + buffer.append(" filePattern=\"" + ScilabXMLUtilities.getXMLString(mySearch.filePattern) + "\""); + buffer.append(" fileCaseSensitive=\"" + mySearch.fileCaseSensitive + "\""); + if (mySearch.wordPattern != null && !mySearch.wordPattern.isEmpty()) { + buffer.append(" wordPattern=\"" + ScilabXMLUtilities.getXMLString(mySearch.wordPattern) + "\""); + } + buffer.append(" wordCaseSensitive=\"" + mySearch.wordCaseSensitive + "\""); + buffer.append(" wholeWord=\"" + mySearch.wholeWord + "\""); + buffer.append(" regexp=\"" + mySearch.regexp + "\""); + buffer.append(">\n"); + mySearch.getResults().toXML(buffer, 1); + buffer.append("</SearchResults>"); + buffer.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void restoreSearchFile() { + File f = new File(ScilabConstants.SCIHOME + File.separator + getPersistentId() + ".xml"); + if (f.exists()) { + Document doc = ScilabXMLUtilities.readDocument(f.getAbsolutePath()); + if (doc != null) { + Element root = doc.getDocumentElement(); + NodeList list = root.getElementsByTagName("Position"); + SearchManager.MatchingPositions pos; + if (list.getLength() != 0) { + pos = new SearchManager.MatchingPositions((Element) list.item(0)); + } else { + return; + } + + String base = root.getAttribute("base"); + boolean recursive = Boolean.parseBoolean(root.getAttribute("recursive")); + boolean ignoreCR = Boolean.parseBoolean(root.getAttribute("ignoreCR")); + String filePattern = root.getAttribute("filePattern").replaceAll(""", "\""); + boolean fileCaseSensitive = Boolean.parseBoolean(root.getAttribute("fileCaseSensitive")); + String wordPattern = root.getAttribute("filePattern").replaceAll(""", "\""); + boolean wordCaseSensitive = Boolean.parseBoolean(root.getAttribute("wordCaseSensitive")); + boolean wholeWord = Boolean.parseBoolean(root.getAttribute("wholeWord")); + boolean regexp = Boolean.parseBoolean(root.getAttribute("regexp")); + + fillTab(pos, base, recursive, ignoreCR, filePattern, fileCaseSensitive, wordPattern, wordCaseSensitive, wholeWord, regexp); + } + } + } + + public void fillTab(SearchManager.MatchingPositions pos, String base, boolean recursive, boolean ignoreCR, + String filePattern, boolean fileCaseSensitive, String wordPattern, + boolean wordCaseSensitive, boolean wholeWord, boolean regexp) { + String title; + + if (wordPattern == null || wordPattern.isEmpty()) { + title = SciNotesMessages.SEARCHFILES; + } else { + title = SciNotesMessages.SEARCHINFILES; + } + + title += " " + SciNotesMessages.FILEPATTERN + ": " + filePattern; + title += ", " + SciNotesMessages.FILECASESENSITIVE + ": " + fileCaseSensitive; + title += ", " + SciNotesMessages.RECURSIVE + ": " + recursive; + if (wordPattern != null && !wordPattern.isEmpty()) { + title += ", " + SciNotesMessages.LINEBYLINE + ": " + !ignoreCR; + if (regexp) { + title += ", " + SciNotesMessages.REGEXPATTERN + ": " + wordPattern; + } else { + title += ", " + SciNotesMessages.WORD + ": " + wordPattern; + } + title += ", " + SciNotesMessages.WORDCASESENSITIVE + ": " + wordCaseSensitive; + title += ", " + SciNotesMessages.WHOLE_WORD + ": " + wholeWord; + } + + tree = getJTree(pos, editor, getInfoBar(), base, recursive, ignoreCR, filePattern, fileCaseSensitive, wordPattern, wordCaseSensitive, wholeWord, regexp); + + setTitle(title); + JScrollPane scrollpane = new JScrollPane(); + setContentPane(scrollpane); + scrollpane.setViewportView(tree); + setVisible(true); + } + + /** + * Initialize the tab + */ + private void initTab() { + final TextBox infobar = ScilabTextBox.createTextBox(); + setWindowIcon("system-search"); + updateUI(); + + CommonCallBack callback = new CommonCallBack(null) { + @Override + public void callBack() { + ClosingOperationsManager.startClosingOperation((SwingScilabDockablePanel) SearchFile.this); + } + + @Override + public void actionPerformed(ActionEvent e) { + callBack(); + } + }; + + setCallback(callback); + MenuBar menubar = ScilabMenuBar.createMenuBar(); + Menu fileMenu = ScilabMenu.createMenu(); + fileMenu.setText(SciNotesMessages.FILE); + fileMenu.setMnemonic('F'); + MenuItem menu = ScilabMenuItem.createMenuItem(); + menu.setCallback(callback); + ((SwingScilabMenuItem) menu.getAsSimpleMenuItem()).setAccelerator(SciNotes.getActionKeys().get("scinotes-exit")); + menu.setText(SciNotesMessages.EXIT); + fileMenu.add(menu); + menubar.add(fileMenu); + + addMenuBar(menubar); + addInfoBar(infobar); + + setPreferredSize(new Dimension(650, 250)); + } + + /** + * @return the JTree int this tab + */ + public JTree getJTree() { + return tree; + } + + /** + * Get a JTree with the results of a search + * @param editor the editor where to open a file + * @param statusbar if non null the status bar where to write file info + * @param base the base directory + * @param recursive, if true then a recursive search is made + * @param ignoreCR, if true then the read file is considered as one line and regex pattern can include \n + * @param filePattern the pattern to use to select the files. * is equivalent to .* and ? to .? + * @param fileCaseSensitive, if true then the file pattern is case sensitive + * @param wordPattern the pattern of the word to search + * @param wordCaseSensitive, if true then the word pattern is case sensitive + * @param wholeWord, if true only whole word will be matched, e.g. in "foobar foo bar", if the pattern is "foo", then only the second "foo" will be matched + * @param regexp, if true the word pattern is considered as a regex + * @return the corresponding JTree + */ + public static JTree getJTree(SearchManager.MatchingPositions files, final SciNotes editor, final TextBox statusbar, + String base, boolean recursive, boolean ignoreCR, + String filePattern, boolean fileCaseSensitive, + String wordPattern, boolean wordCaseSensitive, boolean wholeWord, boolean regexp) { + if (files == null) { + List<SearchManager.MatchingPositions> list = new ArrayList<SearchManager.MatchingPositions>(); + files = new SearchManager.MatchingPositions(new File(base).getAbsolutePath(), list); + files.setRoot(); + } + + Pattern word = null; + if (wordPattern != null && wordPattern.length() != 0) { + word = SearchManager.generatePattern(wordPattern, wordCaseSensitive, wholeWord, regexp); + } + final Pattern p = word; + + files.setRoot(); + final JTree tree = new JTree(files.toDefaultMutableTreeNode()); + MouseListener ml = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + int row = tree.getRowForLocation(e.getX(), e.getY()); + if (row != -1) { + if (e.getClickCount() == 2) { + validNode(editor, p, tree.getPathForRow(row)); + } + } + } + }; + tree.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "toggle"); + tree.addKeyListener(new KeyAdapter() { + public void keyTyped(KeyEvent e) { + if (e.getKeyChar() == '\n') { + int row = tree.getMinSelectionRow(); + if (row != -1) { + validNode(editor, p, tree.getPathForRow(row)); + } + } + } + }); + tree.addMouseListener(ml); + DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer() { + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, + boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + DefaultMutableTreeNode mtn = (DefaultMutableTreeNode) value; + SearchManager.Iconable pos = (SearchManager.Iconable) mtn.getUserObject(); + this.setIcon(pos.getIcon()); + return this; + } + }; + if (statusbar != null) { + tree.addTreeSelectionListener(new TreeSelectionListener() { + @Override + public void valueChanged(TreeSelectionEvent e) { + TreePath path = e.getNewLeadSelectionPath(); + Object userObj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject(); + if (userObj instanceof SearchManager.MatchingPositions) { + statusbar.setText(((SearchManager.MatchingPositions) userObj).getFileName()); + } else if (userObj instanceof SearchManager.Line) { + userObj = ((DefaultMutableTreeNode) ((DefaultMutableTreeNode) path.getLastPathComponent()).getParent()).getUserObject(); + statusbar.setText(((SearchManager.MatchingPositions) userObj).getFileName()); + } + } + }); + } + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.setCellRenderer(renderer); + + return tree; + } + + /** + * Display a window containing the results of the search. + * @param component the component which start the search. It is prevented that search is done via a firePropertyChange (SEARCHDONE). + * @param editor the editor where to open a file + * @param base the base directory + * @param recursive, if true then a recursive search is made + * @param ignoreCR, if true then the read file is considered as one line and regex pattern can include \n + * @param filePattern the pattern to use to select the files. * is equivalent to .* and ? to .? + * @param fileCaseSensitive, if true then the file pattern is case sensitive + * @param wordPattern the pattern of the word to search + * @param wordCaseSensitive, if true then the word pattern is case sensitive + * @param wholeWord, if true only whole word will be matched, e.g. in "foobar foo bar", if the pattern is "foo", then only the second "foo" will be matched + * @param regexp, if true the word pattern is considered as a regex + * @return a key, can be used to stop the search + */ + public static Object getSearchResultsWindow(JComponent component, SciNotes editor, String base, + boolean recursive, boolean ignoreCR, + String filePattern, boolean fileCaseSensitive, + String wordPattern, boolean wordCaseSensitive, boolean wholeWord, boolean regexp) { + MyBackgroundSearch searcher = new MyBackgroundSearch(component, editor, base, recursive, ignoreCR, filePattern, fileCaseSensitive, wordPattern, wordCaseSensitive, wholeWord, regexp); + searcher.start(); + return searcher; + } + + /** + * Stop the current search + * @param searcher the key returned by getSearchResultsWindow + */ + public static void stopSearch(Object searcher) { + if (searcher != null && (searcher instanceof MyBackgroundSearch)) { + ((MyBackgroundSearch) searcher).stop(); + } + } + + /** + * Stop the current search + * @param searcher the key returned by getSearchResultsWindow + */ + public static boolean isDone(Object searcher) { + if (searcher != null && (searcher instanceof MyBackgroundSearch)) { + return ((MyBackgroundSearch) searcher).isDone(); + } + return true; + } + + /** + * If the user hits ENTER key or double-click on a node, the corresponding file is open in SciNotes. + * @param editor the editor where to open the file + * @param the word pattern used + * @param path the path of the node + */ + private static void validNode(SciNotes editor, final Pattern pat, TreePath path) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent(); + Object userObj = node.getUserObject(); + int lineNumber = -1; + String fileName = null; + boolean line = false; + if (userObj instanceof SearchManager.MatchingPositions) { + SearchManager.MatchingPositions pos = (SearchManager.MatchingPositions) userObj; + lineNumber = 0; + if (!pos.isDirectory()) { + fileName = pos.getFileName(); + } + } else if (userObj instanceof SearchManager.Line) { + SearchManager.Line l = (SearchManager.Line) userObj; + lineNumber = l.getNumber(); + fileName = ((SearchManager.MatchingPositions) ((DefaultMutableTreeNode) node.getParent()).getUserObject()).getFileName(); + line = true; + } + + if (fileName != null) { + final boolean fline = !line; + final int ln = lineNumber; + if (lineNumber != -1) { + editor.openFile(fileName, 0, null); + final ScilabEditorPane sep = editor.getTextPane(); + if (sep.getName().equals(fileName)) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + sep.highlightWords(pat, fline); + if (ln != 0) { + sep.scrollTextToLineNumber(ln, false, false, true); + } + } + }); + } + } + } + } + + /** + * Inner class to allow the make the search as a background task (with a SwingWorker). + * The task does not block SciNotes and can be killed by the user. + */ + private static class MyBackgroundSearch extends SearchManager.BackgroundSearch { + + SciNotes editor; + JComponent component; + String base; + boolean recursive; + boolean ignoreCR; + String filePattern; + boolean fileCaseSensitive; + String wordPattern; + boolean wordCaseSensitive; + boolean wholeWord; + boolean regexp; + + /** + * Default constructor + * @param component the component which start the search. It is prevented that search is done via a firePropertyChange (SEARCHDONE). + * @param editor the editor where to open a file + * @param base the base directory + * @param recursive, if true then a recursive search is made + * @param ignoreCR, if true then the read file is considered as one line and regex pattern can include \n + * @param filePattern the pattern to use to select the files. * is equivalent to .* and ? to .? + * @param fileCaseSensitive, if true then the file pattern is case sensitive + * @param wordPattern the pattern of the word to search + * @param wordCaseSensitive, if true then the word pattern is case sensitive + * @param wholeWord, if true only whole word will be matched, e.g. in "foobar foo bar", if the pattern is "foo", then only the second "foo" will be matched + * @param regexp, if true the word pattern is considered as a regex + */ + public MyBackgroundSearch(JComponent component, SciNotes editor, String base, boolean recursive, boolean ignoreCR, + String filePattern, boolean fileCaseSensitive, + String wordPattern, boolean wordCaseSensitive, boolean wholeWord, boolean regexp) { + super(); + this.component = component; + this.editor = editor; + this.base = base; + this.recursive = recursive; + this.ignoreCR = ignoreCR; + this.filePattern = filePattern; + this.fileCaseSensitive = fileCaseSensitive; + this.wordPattern = wordPattern; + this.wordCaseSensitive = wordCaseSensitive; + this.wholeWord = wholeWord; + this.regexp = regexp; + } + + /** + * Starts the search + */ + synchronized public void start() { + SearchManager.searchInFiles(this, base, recursive, ignoreCR, filePattern, fileCaseSensitive, wordPattern, wordCaseSensitive, wholeWord, regexp); + } + + /** + * Stop the search and fire a propertyChange + */ + @Override + synchronized public void stop() { + super.stop(); + if (component != null) { + component.firePropertyChange(SEARCHDONE, false, true); + } + } + + /** + * Called when the results are available + */ + @Override + synchronized public void done() { + SearchManager.MatchingPositions pos = getResults(); + if (pos == null) { + if (component != null) { + component.firePropertyChange(SEARCHDONE, false, true); + } + return; + } + + SearchFile searchFile = editor.getSearchInFiles(); + final SearchFile sf; + if (searchFile == null) { + editor.addSearchInFiles(); + sf = editor.getSearchInFiles(); + } else { + sf = searchFile; + } + + sf.fillTab(pos, base, recursive, ignoreCR, filePattern, fileCaseSensitive, wordPattern, wordCaseSensitive, wholeWord, regexp); + sf.setMyBackgroundSearch(this); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + sf.getJTree().addSelectionRow(0); + sf.getJTree().requestFocus(); + long time = getElapsedTime(); + + sf.getInfoBar().setText(String.format(SciNotesMessages.ELAPSEDTIME, ((double) time) / 1000)); + } + }); + + if (component != null) { + component.firePropertyChange(SEARCHDONE, false, true); + } + } + } +} diff --git a/modules/scinotes/src/jni/.deps/.dirstamp b/modules/scinotes/src/jni/.deps/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/jni/.deps/.dirstamp diff --git a/modules/scinotes/src/jni/.deps/libsciscinotes_algo_la-SciNotes.Plo b/modules/scinotes/src/jni/.deps/libsciscinotes_algo_la-SciNotes.Plo new file mode 100755 index 000000000..ab65a4066 --- /dev/null +++ b/modules/scinotes/src/jni/.deps/libsciscinotes_algo_la-SciNotes.Plo @@ -0,0 +1,341 @@ +src/jni/libsciscinotes_algo_la-SciNotes.lo: src/jni/SciNotes.cpp \ + /usr/include/stdc-predef.h src/jni/SciNotes.hxx \ + /usr/include/c++/5/iostream \ + /usr/include/x86_64-linux-gnu/c++/5/bits/c++config.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/cpu_defines.h \ + /usr/include/c++/5/ostream /usr/include/c++/5/ios \ + /usr/include/c++/5/iosfwd /usr/include/c++/5/bits/stringfwd.h \ + /usr/include/c++/5/bits/memoryfwd.h /usr/include/c++/5/bits/postypes.h \ + /usr/include/c++/5/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/bits/wchar2.h /usr/include/c++/5/exception \ + /usr/include/c++/5/bits/atomic_lockfree_defines.h \ + /usr/include/c++/5/bits/char_traits.h \ + /usr/include/c++/5/bits/stl_algobase.h \ + /usr/include/c++/5/bits/functexcept.h \ + /usr/include/c++/5/bits/exception_defines.h \ + /usr/include/c++/5/bits/cpp_type_traits.h \ + /usr/include/c++/5/ext/type_traits.h \ + /usr/include/c++/5/ext/numeric_traits.h \ + /usr/include/c++/5/bits/stl_pair.h /usr/include/c++/5/bits/move.h \ + /usr/include/c++/5/bits/concept_check.h \ + /usr/include/c++/5/bits/stl_iterator_base_types.h \ + /usr/include/c++/5/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/5/debug/debug.h /usr/include/c++/5/bits/stl_iterator.h \ + /usr/include/c++/5/bits/ptr_traits.h \ + /usr/include/c++/5/bits/predefined_ops.h \ + /usr/include/c++/5/bits/localefwd.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/c++locale.h \ + /usr/include/c++/5/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/5/cctype \ + /usr/include/ctype.h /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap-16.h \ + /usr/include/c++/5/bits/ios_base.h /usr/include/c++/5/ext/atomicity.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/gthr.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/timex.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/atomic_word.h \ + /usr/include/c++/5/bits/locale_classes.h /usr/include/c++/5/string \ + /usr/include/c++/5/bits/allocator.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h \ + /usr/include/c++/5/ext/new_allocator.h /usr/include/c++/5/new \ + /usr/include/c++/5/bits/ostream_insert.h \ + /usr/include/c++/5/bits/cxxabi_forced.h \ + /usr/include/c++/5/bits/stl_function.h \ + /usr/include/c++/5/backward/binders.h \ + /usr/include/c++/5/bits/range_access.h \ + /usr/include/c++/5/bits/basic_string.h \ + /usr/include/c++/5/ext/alloc_traits.h \ + /usr/include/c++/5/bits/basic_string.tcc \ + /usr/include/c++/5/bits/locale_classes.tcc /usr/include/c++/5/stdexcept \ + /usr/include/c++/5/streambuf /usr/include/c++/5/bits/streambuf.tcc \ + /usr/include/c++/5/bits/basic_ios.h \ + /usr/include/c++/5/bits/locale_facets.h /usr/include/c++/5/cwctype \ + /usr/include/wctype.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/ctype_base.h \ + /usr/include/c++/5/bits/streambuf_iterator.h \ + /usr/include/x86_64-linux-gnu/c++/5/bits/ctype_inline.h \ + /usr/include/c++/5/bits/locale_facets.tcc \ + /usr/include/c++/5/bits/basic_ios.tcc \ + /usr/include/c++/5/bits/ostream.tcc /usr/include/c++/5/istream \ + /usr/include/c++/5/bits/istream.tcc /usr/include/string.h \ + /usr/include/x86_64-linux-gnu/bits/string3.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/select2.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-float.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib.h \ + /usr/lib/jvm/java-8-openjdk-amd64/include/jni.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ + /usr/include/x86_64-linux-gnu/bits/stdio.h \ + /usr/include/x86_64-linux-gnu/bits/stdio2.h \ + /usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h \ + ../../modules/commons/src/jni/GiwsException.hxx + +/usr/include/stdc-predef.h: + +src/jni/SciNotes.hxx: + +/usr/include/c++/5/iostream: + +/usr/include/x86_64-linux-gnu/c++/5/bits/c++config.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/cpu_defines.h: + +/usr/include/c++/5/ostream: + +/usr/include/c++/5/ios: + +/usr/include/c++/5/iosfwd: + +/usr/include/c++/5/bits/stringfwd.h: + +/usr/include/c++/5/bits/memoryfwd.h: + +/usr/include/c++/5/bits/postypes.h: + +/usr/include/c++/5/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/bits/wchar2.h: + +/usr/include/c++/5/exception: + +/usr/include/c++/5/bits/atomic_lockfree_defines.h: + +/usr/include/c++/5/bits/char_traits.h: + +/usr/include/c++/5/bits/stl_algobase.h: + +/usr/include/c++/5/bits/functexcept.h: + +/usr/include/c++/5/bits/exception_defines.h: + +/usr/include/c++/5/bits/cpp_type_traits.h: + +/usr/include/c++/5/ext/type_traits.h: + +/usr/include/c++/5/ext/numeric_traits.h: + +/usr/include/c++/5/bits/stl_pair.h: + +/usr/include/c++/5/bits/move.h: + +/usr/include/c++/5/bits/concept_check.h: + +/usr/include/c++/5/bits/stl_iterator_base_types.h: + +/usr/include/c++/5/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/5/debug/debug.h: + +/usr/include/c++/5/bits/stl_iterator.h: + +/usr/include/c++/5/bits/ptr_traits.h: + +/usr/include/c++/5/bits/predefined_ops.h: + +/usr/include/c++/5/bits/localefwd.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/c++locale.h: + +/usr/include/c++/5/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/5/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: + +/usr/include/c++/5/bits/ios_base.h: + +/usr/include/c++/5/ext/atomicity.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/gthr.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/timex.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/atomic_word.h: + +/usr/include/c++/5/bits/locale_classes.h: + +/usr/include/c++/5/string: + +/usr/include/c++/5/bits/allocator.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/c++allocator.h: + +/usr/include/c++/5/ext/new_allocator.h: + +/usr/include/c++/5/new: + +/usr/include/c++/5/bits/ostream_insert.h: + +/usr/include/c++/5/bits/cxxabi_forced.h: + +/usr/include/c++/5/bits/stl_function.h: + +/usr/include/c++/5/backward/binders.h: + +/usr/include/c++/5/bits/range_access.h: + +/usr/include/c++/5/bits/basic_string.h: + +/usr/include/c++/5/ext/alloc_traits.h: + +/usr/include/c++/5/bits/basic_string.tcc: + +/usr/include/c++/5/bits/locale_classes.tcc: + +/usr/include/c++/5/stdexcept: + +/usr/include/c++/5/streambuf: + +/usr/include/c++/5/bits/streambuf.tcc: + +/usr/include/c++/5/bits/basic_ios.h: + +/usr/include/c++/5/bits/locale_facets.h: + +/usr/include/c++/5/cwctype: + +/usr/include/wctype.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/ctype_base.h: + +/usr/include/c++/5/bits/streambuf_iterator.h: + +/usr/include/x86_64-linux-gnu/c++/5/bits/ctype_inline.h: + +/usr/include/c++/5/bits/locale_facets.tcc: + +/usr/include/c++/5/bits/basic_ios.tcc: + +/usr/include/c++/5/bits/ostream.tcc: + +/usr/include/c++/5/istream: + +/usr/include/c++/5/bits/istream.tcc: + +/usr/include/string.h: + +/usr/include/x86_64-linux-gnu/bits/string3.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/select2.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib.h: + +/usr/lib/jvm/java-8-openjdk-amd64/include/jni.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/x86_64-linux-gnu/bits/stdio.h: + +/usr/include/x86_64-linux-gnu/bits/stdio2.h: + +/usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h: + +../../modules/commons/src/jni/GiwsException.hxx: diff --git a/modules/scinotes/src/jni/.deps/libsciscinotes_algo_la-ScilabKeywords_wrap.Plo b/modules/scinotes/src/jni/.deps/libsciscinotes_algo_la-ScilabKeywords_wrap.Plo new file mode 100755 index 000000000..e771b537b --- /dev/null +++ b/modules/scinotes/src/jni/.deps/libsciscinotes_algo_la-ScilabKeywords_wrap.Plo @@ -0,0 +1,134 @@ +src/jni/libsciscinotes_algo_la-ScilabKeywords_wrap.lo: \ + src/jni/ScilabKeywords_wrap.c /usr/include/stdc-predef.h \ + /usr/lib/jvm/java-8-openjdk-amd64/include/jni.h /usr/include/stdio.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ + /usr/include/x86_64-linux-gnu/bits/stdio.h \ + /usr/include/x86_64-linux-gnu/bits/stdio2.h \ + /usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap-16.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/select2.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib-float.h \ + /usr/include/x86_64-linux-gnu/bits/stdlib.h /usr/include/string.h \ + /usr/include/xlocale.h /usr/include/x86_64-linux-gnu/bits/string.h \ + /usr/include/x86_64-linux-gnu/bits/string2.h \ + /usr/include/x86_64-linux-gnu/bits/string3.h \ + ../../modules/core/includes/MALLOC.h \ + ../../modules/core/includes/sci_mem_alloc.h src/c/ScilabKeywords.h + +/usr/include/stdc-predef.h: + +/usr/lib/jvm/java-8-openjdk-amd64/include/jni.h: + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/x86_64-linux-gnu/bits/stdio.h: + +/usr/include/x86_64-linux-gnu/bits/stdio2.h: + +/usr/lib/jvm/java-8-openjdk-amd64/include/linux/jni_md.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap-16.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/select2.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-bsearch.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib-float.h: + +/usr/include/x86_64-linux-gnu/bits/stdlib.h: + +/usr/include/string.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/bits/string.h: + +/usr/include/x86_64-linux-gnu/bits/string2.h: + +/usr/include/x86_64-linux-gnu/bits/string3.h: + +../../modules/core/includes/MALLOC.h: + +../../modules/core/includes/sci_mem_alloc.h: + +src/c/ScilabKeywords.h: diff --git a/modules/scinotes/src/jni/.dirstamp b/modules/scinotes/src/jni/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/jni/.dirstamp diff --git a/modules/scinotes/src/jni/.libs/libsciscinotes_algo_la-SciNotes.o b/modules/scinotes/src/jni/.libs/libsciscinotes_algo_la-SciNotes.o Binary files differnew file mode 100755 index 000000000..c2fa947b9 --- /dev/null +++ b/modules/scinotes/src/jni/.libs/libsciscinotes_algo_la-SciNotes.o diff --git a/modules/scinotes/src/jni/.libs/libsciscinotes_algo_la-ScilabKeywords_wrap.o b/modules/scinotes/src/jni/.libs/libsciscinotes_algo_la-ScilabKeywords_wrap.o Binary files differnew file mode 100755 index 000000000..f13b87035 --- /dev/null +++ b/modules/scinotes/src/jni/.libs/libsciscinotes_algo_la-ScilabKeywords_wrap.o diff --git a/modules/scinotes/src/jni/SciNotes.cpp b/modules/scinotes/src/jni/SciNotes.cpp new file mode 100755 index 000000000..4aeb80ed9 --- /dev/null +++ b/modules/scinotes/src/jni/SciNotes.cpp @@ -0,0 +1,313 @@ +#include "SciNotes.hxx" +/* Generated by GIWS (version 2.0.2) with command: +giws --disable-return-size-array --output-dir src/jni/ --throws-exception-on-error --description-file src/jni/SciNotes.giws.xml +*/ +/* + +This is generated code. + +This software is a computer program whose purpose is to hide the complexity +of accessing Java objects/methods from C++ code. + +This software is governed by the CeCILL-B license under French law and +abiding by the rules of distribution of free software. You can use, +modify and/ or redistribute the software under the terms of the CeCILL-B +license as circulated by CEA, CNRS and INRIA at the following URL +"http://www.cecill.info". + +As a counterpart to the access to the source code and rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors have only limited +liability. + +In this respect, the user's attention is drawn to the risks associated +with loading, using, modifying and/or developing or reproducing the +software by the user in light of its specific status of free software, +that may mean that it is complicated to manipulate, and that also +therefore means that it is reserved for developers and experienced +professionals having in-depth computer knowledge. Users are therefore +encouraged to load and test the software's suitability as regards their +requirements in conditions enabling the security of their systems and/or +data to be ensured and, more generally, to use and operate it in the +same conditions as regards security. + +The fact that you are presently reading this means that you have had +knowledge of the CeCILL-B license and that you accept its terms. +*/ + +namespace org_scilab_modules_scinotes { + + // Static declarations (if any) + +// Returns the current env + +JNIEnv * SciNotes::getCurrentEnv() { +JNIEnv * curEnv = NULL; +jint res=this->jvm->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +if (res != JNI_OK) { +throw GiwsException::JniException(getCurrentEnv()); +} +return curEnv; +} +// Destructor + +SciNotes::~SciNotes() { +JNIEnv * curEnv = NULL; +this->jvm->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +curEnv->DeleteGlobalRef(this->instance); +curEnv->DeleteGlobalRef(this->instanceClass); +curEnv->DeleteGlobalRef(this->stringArrayClass);} +// Constructors +SciNotes::SciNotes(JavaVM * jvm_) { +jmethodID constructObject = NULL ; +jobject localInstance ; +jclass localClass ; + +const std::string construct="<init>"; +const std::string param="()V"; +jvm=jvm_; + +JNIEnv * curEnv = getCurrentEnv(); + +localClass = curEnv->FindClass( this->className().c_str() ) ; +if (localClass == NULL) { + throw GiwsException::JniClassNotFoundException(curEnv, this->className()); +} + +this->instanceClass = static_cast<jclass>(curEnv->NewGlobalRef(localClass)); + +/* localClass is not needed anymore */ +curEnv->DeleteLocalRef(localClass); + +if (this->instanceClass == NULL) { +throw GiwsException::JniObjectCreationException(curEnv, this->className()); +} + + +constructObject = curEnv->GetMethodID( this->instanceClass, construct.c_str() , param.c_str() ) ; +if(constructObject == NULL){ +throw GiwsException::JniObjectCreationException(curEnv, this->className()); +} + +localInstance = curEnv->NewObject( this->instanceClass, constructObject ) ; +if(localInstance == NULL){ +throw GiwsException::JniObjectCreationException(curEnv, this->className()); +} + +this->instance = curEnv->NewGlobalRef(localInstance) ; +if(this->instance == NULL){ +throw GiwsException::JniObjectCreationException(curEnv, this->className()); +} +/* localInstance not needed anymore */ +curEnv->DeleteLocalRef(localInstance); + + /* Methods ID set to NULL */ +voidscinotesID=NULL; +voidscinotesjstringjava_lang_StringID=NULL; +voidscinotesjstringjava_lang_Stringjintintjstringjava_lang_StringID=NULL; +voidscinotesjstringjava_lang_StringjobjectArray_java_lang_Stringjava_lang_StringID=NULL; +voidcloseSciNotesFromScilabID=NULL; + + +} + +SciNotes::SciNotes(JavaVM * jvm_, jobject JObj) { + jvm=jvm_; + + JNIEnv * curEnv = getCurrentEnv(); + +jclass localClass = curEnv->GetObjectClass(JObj); + this->instanceClass = static_cast<jclass>(curEnv->NewGlobalRef(localClass)); + curEnv->DeleteLocalRef(localClass); + + if (this->instanceClass == NULL) { +throw GiwsException::JniObjectCreationException(curEnv, this->className()); + } + + this->instance = curEnv->NewGlobalRef(JObj) ; + if(this->instance == NULL){ +throw GiwsException::JniObjectCreationException(curEnv, this->className()); + } + /* Methods ID set to NULL */ + voidscinotesID=NULL; +voidscinotesjstringjava_lang_StringID=NULL; +voidscinotesjstringjava_lang_Stringjintintjstringjava_lang_StringID=NULL; +voidscinotesjstringjava_lang_StringjobjectArray_java_lang_Stringjava_lang_StringID=NULL; +voidcloseSciNotesFromScilabID=NULL; + + +} + +// Generic methods + +void SciNotes::synchronize() { +if (getCurrentEnv()->MonitorEnter(instance) != JNI_OK) { +throw GiwsException::JniMonitorException(getCurrentEnv(), "SciNotes"); +} +} + +void SciNotes::endSynchronize() { +if ( getCurrentEnv()->MonitorExit(instance) != JNI_OK) { +throw GiwsException::JniMonitorException(getCurrentEnv(), "SciNotes"); +} +} +// Method(s) + +void SciNotes::scinotes (JavaVM * jvm_){ + +JNIEnv * curEnv = NULL; +jvm_->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +jclass cls = initClass(curEnv); +if ( cls == NULL) { +throw GiwsException::JniCallMethodException(curEnv); +} + +static jmethodID voidscinotesID = curEnv->GetStaticMethodID(cls, "scinotes", "()V" ) ; +if (voidscinotesID == NULL) { +throw GiwsException::JniMethodNotFoundException(curEnv, "scinotes"); +} + + curEnv->CallStaticVoidMethod(cls, voidscinotesID ); + if (curEnv->ExceptionCheck()) { +throw GiwsException::JniCallMethodException(curEnv); +} +} + +void SciNotes::scinotes (JavaVM * jvm_, char const* fileName){ + +JNIEnv * curEnv = NULL; +jvm_->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +jclass cls = initClass(curEnv); +if ( cls == NULL) { +throw GiwsException::JniCallMethodException(curEnv); +} + +static jmethodID voidscinotesjstringjava_lang_StringID = curEnv->GetStaticMethodID(cls, "scinotes", "(Ljava/lang/String;)V" ) ; +if (voidscinotesjstringjava_lang_StringID == NULL) { +throw GiwsException::JniMethodNotFoundException(curEnv, "scinotes"); +} + +jstring fileName_ = curEnv->NewStringUTF( fileName ); +if (fileName != NULL && fileName_ == NULL) +{ +throw GiwsException::JniBadAllocException(curEnv); +} + + + curEnv->CallStaticVoidMethod(cls, voidscinotesjstringjava_lang_StringID ,fileName_); + curEnv->DeleteLocalRef(fileName_); +if (curEnv->ExceptionCheck()) { +throw GiwsException::JniCallMethodException(curEnv); +} +} + +void SciNotes::scinotes (JavaVM * jvm_, char const* fileName, int lineNumber, char const* functionName){ + +JNIEnv * curEnv = NULL; +jvm_->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +jclass cls = initClass(curEnv); +if ( cls == NULL) { +throw GiwsException::JniCallMethodException(curEnv); +} + +static jmethodID voidscinotesjstringjava_lang_Stringjintintjstringjava_lang_StringID = curEnv->GetStaticMethodID(cls, "scinotes", "(Ljava/lang/String;ILjava/lang/String;)V" ) ; +if (voidscinotesjstringjava_lang_Stringjintintjstringjava_lang_StringID == NULL) { +throw GiwsException::JniMethodNotFoundException(curEnv, "scinotes"); +} + +jstring fileName_ = curEnv->NewStringUTF( fileName ); +if (fileName != NULL && fileName_ == NULL) +{ +throw GiwsException::JniBadAllocException(curEnv); +} + + +jstring functionName_ = curEnv->NewStringUTF( functionName ); +if (functionName != NULL && functionName_ == NULL) +{ +throw GiwsException::JniBadAllocException(curEnv); +} + + + curEnv->CallStaticVoidMethod(cls, voidscinotesjstringjava_lang_Stringjintintjstringjava_lang_StringID ,fileName_, lineNumber, functionName_); + curEnv->DeleteLocalRef(fileName_); +curEnv->DeleteLocalRef(functionName_); +if (curEnv->ExceptionCheck()) { +throw GiwsException::JniCallMethodException(curEnv); +} +} + +void SciNotes::scinotes (JavaVM * jvm_, char const* fileName, char const* const* option, int optionSize){ + +JNIEnv * curEnv = NULL; +jvm_->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +jclass cls = initClass(curEnv); +if ( cls == NULL) { +throw GiwsException::JniCallMethodException(curEnv); +} + +static jmethodID voidscinotesjstringjava_lang_StringjobjectArray_java_lang_Stringjava_lang_StringID = curEnv->GetStaticMethodID(cls, "scinotes", "(Ljava/lang/String;[Ljava/lang/String;)V" ) ; +if (voidscinotesjstringjava_lang_StringjobjectArray_java_lang_Stringjava_lang_StringID == NULL) { +throw GiwsException::JniMethodNotFoundException(curEnv, "scinotes"); +} + +jstring fileName_ = curEnv->NewStringUTF( fileName ); +if (fileName != NULL && fileName_ == NULL) +{ +throw GiwsException::JniBadAllocException(curEnv); +} + +jclass stringArrayClass = curEnv->FindClass("java/lang/String"); + +// create java array of strings. +jobjectArray option_ = curEnv->NewObjectArray( optionSize, stringArrayClass, NULL); +if (option_ == NULL) +{ +throw GiwsException::JniBadAllocException(curEnv); +} + +// convert each char * to java strings and fill the java array. +for ( int i = 0; i < optionSize; i++) +{ +jstring TempString = curEnv->NewStringUTF( option[i] ); +if (TempString == NULL) +{ +throw GiwsException::JniBadAllocException(curEnv); +} + +curEnv->SetObjectArrayElement( option_, i, TempString); + +// avoid keeping reference on too many strings +curEnv->DeleteLocalRef(TempString); +} + curEnv->CallStaticVoidMethod(cls, voidscinotesjstringjava_lang_StringjobjectArray_java_lang_Stringjava_lang_StringID ,fileName_, option_); + curEnv->DeleteLocalRef(stringArrayClass); +curEnv->DeleteLocalRef(fileName_); +curEnv->DeleteLocalRef(option_); +if (curEnv->ExceptionCheck()) { +throw GiwsException::JniCallMethodException(curEnv); +} +} + +void SciNotes::closeSciNotesFromScilab (JavaVM * jvm_){ + +JNIEnv * curEnv = NULL; +jvm_->AttachCurrentThread(reinterpret_cast<void **>(&curEnv), NULL); +jclass cls = initClass(curEnv); +if ( cls == NULL) { +throw GiwsException::JniCallMethodException(curEnv); +} + +static jmethodID voidcloseSciNotesFromScilabID = curEnv->GetStaticMethodID(cls, "closeSciNotesFromScilab", "()V" ) ; +if (voidcloseSciNotesFromScilabID == NULL) { +throw GiwsException::JniMethodNotFoundException(curEnv, "closeSciNotesFromScilab"); +} + + curEnv->CallStaticVoidMethod(cls, voidcloseSciNotesFromScilabID ); + if (curEnv->ExceptionCheck()) { +throw GiwsException::JniCallMethodException(curEnv); +} +} + +} diff --git a/modules/scinotes/src/jni/SciNotes.giws.xml b/modules/scinotes/src/jni/SciNotes.giws.xml new file mode 100755 index 000000000..1ffa0e667 --- /dev/null +++ b/modules/scinotes/src/jni/SciNotes.giws.xml @@ -0,0 +1,18 @@ + <package name="org.scilab.modules.scinotes"> + <object name="SciNotes"> + <method name="scinotes" returnType="void" modifier="static"/> + <method name="scinotes" returnType="void" modifier="static"> + <parameter name="fileName" type="String"/> + </method> + <method name="scinotes" returnType="void" modifier="static"> + <parameter name="fileName" type="String"/> + <parameter name="lineNumber" type="int"/> + <parameter name="functionName" type="String"/> + </method> + <method name="scinotes" returnType="void" modifier="static"> + <parameter name="fileName" type="String"/> + <parameter name="option" type="String[]"/> + </method> + <method name="closeSciNotesFromScilab" returnType="void" modifier="static"/> + </object> +</package> diff --git a/modules/scinotes/src/jni/SciNotes.hxx b/modules/scinotes/src/jni/SciNotes.hxx new file mode 100755 index 000000000..27fc3f132 --- /dev/null +++ b/modules/scinotes/src/jni/SciNotes.hxx @@ -0,0 +1,191 @@ +/* Generated by GIWS (version 2.0.2) with command: +giws --disable-return-size-array --output-dir src/jni/ --throws-exception-on-error --description-file src/jni/SciNotes.giws.xml +*/ +/* + +This is generated code. + +This software is a computer program whose purpose is to hide the complexity +of accessing Java objects/methods from C++ code. + +This software is governed by the CeCILL-B license under French law and +abiding by the rules of distribution of free software. You can use, +modify and/ or redistribute the software under the terms of the CeCILL-B +license as circulated by CEA, CNRS and INRIA at the following URL +"http://www.cecill.info". + +As a counterpart to the access to the source code and rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors have only limited +liability. + +In this respect, the user's attention is drawn to the risks associated +with loading, using, modifying and/or developing or reproducing the +software by the user in light of its specific status of free software, +that may mean that it is complicated to manipulate, and that also +therefore means that it is reserved for developers and experienced +professionals having in-depth computer knowledge. Users are therefore +encouraged to load and test the software's suitability as regards their +requirements in conditions enabling the security of their systems and/or +data to be ensured and, more generally, to use and operate it in the +same conditions as regards security. + +The fact that you are presently reading this means that you have had +knowledge of the CeCILL-B license and that you accept its terms. +*/ + + +#ifndef __ORG_SCILAB_MODULES_SCINOTES_SCINOTES__ +#define __ORG_SCILAB_MODULES_SCINOTES_SCINOTES__ +#include <iostream> +#include <string> +#include <string.h> +#include <stdlib.h> +#include <jni.h> + +#include "GiwsException.hxx" + + #if defined(_MSC_VER) /* Defined anyway with Visual */ + #include <Windows.h> + #else + typedef signed char byte; + #endif + + +#ifndef GIWSEXPORT +# if defined(_MSC_VER) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define GIWSEXPORT +# else +# define GIWSEXPORT __declspec(dllexport) +# endif +# else +# if __GNUC__ >= 4 +# define GIWSEXPORT __attribute__ ((visibility ("default"))) +# else +# define GIWSEXPORT +# endif +# endif +#endif + +namespace org_scilab_modules_scinotes { +class GIWSEXPORT SciNotes { + +private: +JavaVM * jvm; + +protected: +jmethodID voidscinotesID; // cache method id +jmethodID voidscinotesjstringjava_lang_StringID; // cache method id +jmethodID voidscinotesjstringjava_lang_Stringjintintjstringjava_lang_StringID; // cache method id +jmethodID voidscinotesjstringjava_lang_StringjobjectArray_java_lang_Stringjava_lang_StringID; // cache method id +jclass stringArrayClass; +jmethodID voidcloseSciNotesFromScilabID; // cache method id + + + +jobject instance; +jclass instanceClass; // cache class + + +// Caching (if any) + + +/** +* Get the environment matching to the current thread. +*/ +virtual JNIEnv * getCurrentEnv(); + +public: +// Constructor +/** +* Create a wrapping of the object from a JNIEnv. +* It will call the default constructor +* @param JEnv_ the Java Env +*/ +SciNotes(JavaVM * jvm_); + +/** +* Create a wrapping of an already existing object from a JNIEnv. +* The object must have already been instantiated +* @param JEnv_ the Java Env +* @param JObj the object +*/ +SciNotes(JavaVM * jvm_, jobject JObj); + + +/** +* This is a fake constructor to avoid the constructor +* chaining when dealing with extended giws classes +*/ +#ifdef FAKEGIWSDATATYPE +SciNotes(fakeGiwsDataType::fakeGiwsDataType /* unused */) {} +#endif + +// Destructor +~SciNotes(); + +// Generic method +// Synchronization methods +/** +* Enter monitor associated with the object. +* Equivalent of creating a "synchronized(obj)" scope in Java. +*/ +void synchronize(); + +/** +* Exit monitor associated with the object. +* Equivalent of ending a "synchronized(obj)" scope. +*/ +void endSynchronize(); + +// Methods +static void scinotes(JavaVM * jvm_); + +static void scinotes(JavaVM * jvm_, char const* fileName); + +static void scinotes(JavaVM * jvm_, char const* fileName, int lineNumber, char const* functionName); + +static void scinotes(JavaVM * jvm_, char const* fileName, char const* const* option, int optionSize); + +static void closeSciNotesFromScilab(JavaVM * jvm_); + + + /** + * Get class name to use for static methods + * @return class name to use for static methods + */ + + static const std::string className() + { + return "org/scilab/modules/scinotes/SciNotes"; + } + + + /** + * Get class to use for static methods + * @return class to use for static methods + */ + + static jclass initClass(JNIEnv * curEnv) + { + static jclass cls = 0; + + if (cls == 0) + { + jclass _cls = curEnv->FindClass(className().c_str()); + if (_cls) + { + cls = static_cast<jclass>(curEnv->NewGlobalRef(_cls)); + } + } + + return cls; + } + +}; + + +} +#endif diff --git a/modules/scinotes/src/jni/ScilabKeywords.i b/modules/scinotes/src/jni/ScilabKeywords.i new file mode 100755 index 000000000..6a20c6c26 --- /dev/null +++ b/modules/scinotes/src/jni/ScilabKeywords.i @@ -0,0 +1,108 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * Copyright (C) 2010 - Calixte DENIZET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +/* ScilabKeywords.i */ +/** + * Windows: swig -java -package org.scilab.modules.scinotes -outdir ../java/org/scilab/modules/scinotes/ ScilabKeywords.i + * Other: Use the option --enable-build-swig to the configure + */ +%module ScilabKeywords + +%{ +#include "MALLOC.h" +#include "ScilabKeywords.h" +%} + +%include "../../../jvm/src/jni/scilab_typemaps.i" + +/* JavaDoc for ScilabKeywordsJNI class */ +%pragma(java) jniclassclassmodifiers=%{ +/* It is generated code. Disable checkstyle */ +//CHECKSTYLE:OFF + /** + * @author Allan CORNET - DIGITEO 2009 + * @author Calixte DENIZET + */ +public class%} + +/* Constructor for ScilabKeywordsJNI class */ +%pragma(java) jniclasscode=" + /** + * Constructor + */ + protected ScilabKeywordsJNI() { + throw new UnsupportedOperationException(); + }"; + +/* static load of library */ +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("sciscinotes"); + } catch (SecurityException e) { + System.err.println("A security manager exists and does not allow the loading of the specified dynamic library."); + System.err.println(e.getLocalizedMessage()); + e.printStackTrace(System.err); + } catch (UnsatisfiedLinkError e) { + if (System.getenv("CONTINUE_ON_JNI_ERROR") == null) { + System.err.println("The native library scinotes does not exist or cannot be found."); + System.err.println(e.getLocalizedMessage()); + e.printStackTrace(System.err); + } + } + } +%} + +/* JavaDoc for ScilabKeywords class */ +%pragma(java) moduleclassmodifiers=" + /** + * @author Allan CORNET - DIGITEO 2009 + * @author Calixte DENIZET + */ +public class"; + +/* Constructor for ScilabKeywords class */ +%pragma(java) modulecode=" + /** + * Constructor + */ + protected ScilabKeywords() { + throw new UnsupportedOperationException(); + }"; + + +/* JavaDoc */ +%javamethodmodifiers GetVariablesName() " +/** +* get Variables Name +* @return an array of chars +*/ +public"; +char **GetVariablesName(void); + +/* JavaDoc */ +%javamethodmodifiers GetFunctionsName() " +/** +* get Functions Name +* @return an array of chars +*/ +public"; +char **GetFunctionsName(void); + +/* JavaDoc */ +%javamethodmodifiers GetMacrosName() " +/** +* get Macros Name +* @return an array of chars +*/ +public"; +char **GetMacrosName(void); diff --git a/modules/scinotes/src/jni/ScilabKeywords_wrap.c b/modules/scinotes/src/jni/ScilabKeywords_wrap.c new file mode 100755 index 000000000..b5eadd6d0 --- /dev/null +++ b/modules/scinotes/src/jni/ScilabKeywords_wrap.c @@ -0,0 +1,303 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.7 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +#define SWIGJAVA + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + + + +/* Fix for jlong on some versions of gcc on Windows */ +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + typedef long long __int64; +#endif + +/* Fix for jlong on 64-bit x86 Solaris */ +#if defined(__x86_64) +# ifdef _LP64 +# undef _LP64 +# endif +#endif + +#include <jni.h> +#include <stdlib.h> +#include <string.h> + + +/* Support for throwing Java exceptions */ +typedef enum { + SWIG_JavaOutOfMemoryError = 1, + SWIG_JavaIOException, + SWIG_JavaRuntimeException, + SWIG_JavaIndexOutOfBoundsException, + SWIG_JavaArithmeticException, + SWIG_JavaIllegalArgumentException, + SWIG_JavaNullPointerException, + SWIG_JavaDirectorPureVirtual, + SWIG_JavaUnknownError +} SWIG_JavaExceptionCodes; + +typedef struct { + SWIG_JavaExceptionCodes code; + const char *java_exception; +} SWIG_JavaExceptions_t; + + +static void SWIGUNUSED SWIG_JavaThrowException(JNIEnv *jenv, SWIG_JavaExceptionCodes code, const char *msg) { + jclass excep; + static const SWIG_JavaExceptions_t java_exceptions[] = { + { SWIG_JavaOutOfMemoryError, "java/lang/OutOfMemoryError" }, + { SWIG_JavaIOException, "java/io/IOException" }, + { SWIG_JavaRuntimeException, "java/lang/RuntimeException" }, + { SWIG_JavaIndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException" }, + { SWIG_JavaArithmeticException, "java/lang/ArithmeticException" }, + { SWIG_JavaIllegalArgumentException, "java/lang/IllegalArgumentException" }, + { SWIG_JavaNullPointerException, "java/lang/NullPointerException" }, + { SWIG_JavaDirectorPureVirtual, "java/lang/RuntimeException" }, + { SWIG_JavaUnknownError, "java/lang/UnknownError" }, + { (SWIG_JavaExceptionCodes)0, "java/lang/UnknownError" } + }; + const SWIG_JavaExceptions_t *except_ptr = java_exceptions; + + while (except_ptr->code != code && except_ptr->code) + except_ptr++; + + (*jenv)->ExceptionClear(jenv); + excep = (*jenv)->FindClass(jenv, except_ptr->java_exception); + if (excep) + (*jenv)->ThrowNew(jenv, excep, msg); +} + + +/* Contract support */ + +#define SWIG_contract_assert(nullreturn, expr, msg) if (!(expr)) {SWIG_JavaThrowException(jenv, SWIG_JavaIllegalArgumentException, msg); return nullreturn; } else + + +#include "MALLOC.h" +#include "ScilabKeywords.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +SWIGEXPORT jobjectArray JNICALL Java_org_scilab_modules_scinotes_ScilabKeywordsJNI_GetVariablesName(JNIEnv *jenv, jclass jcls) { + jobjectArray jresult = 0 ; + char **result = 0 ; + + (void)jenv; + (void)jcls; + result = (char **)GetVariablesName(); + { + if (result != NULL) + { + int i; + int len=0; + jstring temp_string; + const jclass clazz = (*jenv)->FindClass(jenv, "java/lang/String"); + + while (result[len]) len++; + jresult = (*jenv)->NewObjectArray(jenv, len, clazz, NULL); + /* exception checking omitted */ + + for (i=0; i<len; i++) { + temp_string = (*jenv)->NewStringUTF(jenv, result[i]); + (*jenv)->SetObjectArrayElement(jenv, jresult, i, temp_string); + (*jenv)->DeleteLocalRef(jenv, temp_string); + FREE(result[i]); + result[i] = NULL; + } + FREE(result); + result = NULL; + } + } + return jresult; +} + + +SWIGEXPORT jobjectArray JNICALL Java_org_scilab_modules_scinotes_ScilabKeywordsJNI_GetFunctionsName(JNIEnv *jenv, jclass jcls) { + jobjectArray jresult = 0 ; + char **result = 0 ; + + (void)jenv; + (void)jcls; + result = (char **)GetFunctionsName(); + { + if (result != NULL) + { + int i; + int len=0; + jstring temp_string; + const jclass clazz = (*jenv)->FindClass(jenv, "java/lang/String"); + + while (result[len]) len++; + jresult = (*jenv)->NewObjectArray(jenv, len, clazz, NULL); + /* exception checking omitted */ + + for (i=0; i<len; i++) { + temp_string = (*jenv)->NewStringUTF(jenv, result[i]); + (*jenv)->SetObjectArrayElement(jenv, jresult, i, temp_string); + (*jenv)->DeleteLocalRef(jenv, temp_string); + FREE(result[i]); + result[i] = NULL; + } + FREE(result); + result = NULL; + } + } + return jresult; +} + + +SWIGEXPORT jobjectArray JNICALL Java_org_scilab_modules_scinotes_ScilabKeywordsJNI_GetMacrosName(JNIEnv *jenv, jclass jcls) { + jobjectArray jresult = 0 ; + char **result = 0 ; + + (void)jenv; + (void)jcls; + result = (char **)GetMacrosName(); + { + if (result != NULL) + { + int i; + int len=0; + jstring temp_string; + const jclass clazz = (*jenv)->FindClass(jenv, "java/lang/String"); + + while (result[len]) len++; + jresult = (*jenv)->NewObjectArray(jenv, len, clazz, NULL); + /* exception checking omitted */ + + for (i=0; i<len; i++) { + temp_string = (*jenv)->NewStringUTF(jenv, result[i]); + (*jenv)->SetObjectArrayElement(jenv, jresult, i, temp_string); + (*jenv)->DeleteLocalRef(jenv, temp_string); + FREE(result[i]); + result[i] = NULL; + } + FREE(result); + result = NULL; + } + } + return jresult; +} + + +#ifdef __cplusplus +} +#endif + diff --git a/modules/scinotes/src/jni/libsciscinotes_algo_la-SciNotes.lo b/modules/scinotes/src/jni/libsciscinotes_algo_la-SciNotes.lo new file mode 100755 index 000000000..9d1db71d4 --- /dev/null +++ b/modules/scinotes/src/jni/libsciscinotes_algo_la-SciNotes.lo @@ -0,0 +1,12 @@ +# src/jni/libsciscinotes_algo_la-SciNotes.lo - a libtool object file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/libsciscinotes_algo_la-SciNotes.o' + +# Name of the non-PIC object +non_pic_object=none + diff --git a/modules/scinotes/src/jni/libsciscinotes_algo_la-ScilabKeywords_wrap.lo b/modules/scinotes/src/jni/libsciscinotes_algo_la-ScilabKeywords_wrap.lo new file mode 100755 index 000000000..614b6c93a --- /dev/null +++ b/modules/scinotes/src/jni/libsciscinotes_algo_la-ScilabKeywords_wrap.lo @@ -0,0 +1,12 @@ +# src/jni/libsciscinotes_algo_la-ScilabKeywords_wrap.lo - a libtool object file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/libsciscinotes_algo_la-ScilabKeywords_wrap.o' + +# Name of the non-PIC object +non_pic_object=none + diff --git a/modules/scinotes/src/noscinotes/.deps/.dirstamp b/modules/scinotes/src/noscinotes/.deps/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/noscinotes/.deps/.dirstamp diff --git a/modules/scinotes/src/noscinotes/.deps/libsciscinotes_disable_la-noscinotes.Plo b/modules/scinotes/src/noscinotes/.deps/libsciscinotes_disable_la-noscinotes.Plo new file mode 100755 index 000000000..bddd4932b --- /dev/null +++ b/modules/scinotes/src/noscinotes/.deps/libsciscinotes_disable_la-noscinotes.Plo @@ -0,0 +1,57 @@ +src/noscinotes/libsciscinotes_disable_la-noscinotes.lo: \ + src/noscinotes/noscinotes.c /usr/include/stdc-predef.h \ + src/noscinotes/noscinotes.h \ + ../../modules/output_stream/includes/Scierror.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h \ + ../../modules/output_stream/includes/do_error_number.h \ + ../../modules/core/includes/machine.h \ + ../../modules/localization/includes/localization.h \ + /usr/include/libintl.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/xlocale.h \ + ../../modules/core/includes/scilabmode.h \ + ../../modules/core/includes/machine.h ../../modules/core/includes/BOOL.h + +/usr/include/stdc-predef.h: + +src/noscinotes/noscinotes.h: + +../../modules/output_stream/includes/Scierror.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stdarg.h: + +../../modules/output_stream/includes/do_error_number.h: + +../../modules/core/includes/machine.h: + +../../modules/localization/includes/localization.h: + +/usr/include/libintl.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/xlocale.h: + +../../modules/core/includes/scilabmode.h: + +../../modules/core/includes/machine.h: + +../../modules/core/includes/BOOL.h: diff --git a/modules/scinotes/src/noscinotes/.dirstamp b/modules/scinotes/src/noscinotes/.dirstamp new file mode 100755 index 000000000..e69de29bb --- /dev/null +++ b/modules/scinotes/src/noscinotes/.dirstamp diff --git a/modules/scinotes/src/noscinotes/.libs/libsciscinotes_disable_la-noscinotes.o b/modules/scinotes/src/noscinotes/.libs/libsciscinotes_disable_la-noscinotes.o Binary files differnew file mode 100755 index 000000000..1b605f26d --- /dev/null +++ b/modules/scinotes/src/noscinotes/.libs/libsciscinotes_disable_la-noscinotes.o diff --git a/modules/scinotes/src/noscinotes/libsciscinotes_disable_la-noscinotes.lo b/modules/scinotes/src/noscinotes/libsciscinotes_disable_la-noscinotes.lo new file mode 100755 index 000000000..6e0d61653 --- /dev/null +++ b/modules/scinotes/src/noscinotes/libsciscinotes_disable_la-noscinotes.lo @@ -0,0 +1,12 @@ +# src/noscinotes/libsciscinotes_disable_la-noscinotes.lo - a libtool object file +# Generated by libtool (GNU libtool) 2.4.2 +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# Name of the PIC object. +pic_object='.libs/libsciscinotes_disable_la-noscinotes.o' + +# Name of the non-PIC object +non_pic_object=none + diff --git a/modules/scinotes/src/noscinotes/noscinotes.c b/modules/scinotes/src/noscinotes/noscinotes.c new file mode 100755 index 000000000..5fdfeb88d --- /dev/null +++ b/modules/scinotes/src/noscinotes/noscinotes.c @@ -0,0 +1,30 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +/*--------------------------------------------------------------------------*/ +#include "noscinotes.h" +#include "Scierror.h" +#include "localization.h" +#include "scilabmode.h" +/*--------------------------------------------------------------------------*/ +int gw_scinotes(void) +{ + if (getScilabMode() == SCILAB_NWNI) + { + Scierror(999, _("Scilab '%s' module disabled in -nogui or -nwni mode.\n"), "scinotes"); + } + else + { + Scierror(999, _("Scilab '%s' module not installed.\n"), "scinotes"); + } + return 0; +} +/*--------------------------------------------------------------------------*/ diff --git a/modules/scinotes/src/noscinotes/noscinotes.h b/modules/scinotes/src/noscinotes/noscinotes.h new file mode 100755 index 000000000..e444d76db --- /dev/null +++ b/modules/scinotes/src/noscinotes/noscinotes.h @@ -0,0 +1,19 @@ +/* + * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab + * Copyright (C) 2009 - DIGITEO - Allan CORNET + * + * This file must be used under the terms of the CeCILL. + * This source file is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at + * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt + * + */ +/*--------------------------------------------------------------------------*/ +/** + * This function is a wrapper / fake when Scilab is compiled without scinotes + * + * @return 0 + */ +int gw_scinotes(void); +/*--------------------------------------------------------------------------*/ |