Merge branch 'omaha_16.1.1' into field_16.1.1

Entry for NTAT missing from omaha_16.1.1's LevelMappingFile.xml.

Change-Id: I39893e6aa748f7dfeb30bd23bcfca3853fa51e17

Former-commit-id: cc1e4ea67074c41be411c99ce979124a63c7c743
This commit is contained in:
Ana Rivera 2015-07-07 19:41:48 +00:00
commit e075f22bf7
260 changed files with 10283 additions and 4432 deletions

View file

@ -1,4 +1,5 @@
#!/bin/bash
# Temporary, only be used until we get DOD certs.
# rewrite from 16.1.1
SETUP_ENV=/awips2/edex/bin/setup.env
@ -273,7 +274,6 @@ do
done
cn=$(hostname)
echo "Generating keystore..."

View file

@ -100,6 +100,16 @@
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
</bean>
-->
<bean id="appInfo" class="com.raytheon.uf.common.util.app.AppInfo" factory-method="initialize">
<constructor-arg value="EDEX"/>
<!-- TODO provide some mechanism to get the version. -->
<constructor-arg>
<null />
</constructor-arg>
<constructor-arg value="${edex.run.mode}"/>
</bean>
<bean id="httpClientConfigBuilder" class="com.raytheon.uf.common.comm.HttpClientConfigBuilder">
<property name="maxConnections" value="${PYPIES_MAX_CONN}"/>
@ -109,7 +119,7 @@
<bean id="httpClientConfig" factory-bean="httpClientConfigBuilder" factory-method="build"/>
<bean id="httpClient" class="com.raytheon.uf.common.comm.HttpClient" factory-method="configureGlobalInstance">
<bean id="httpClient" class="com.raytheon.uf.common.comm.HttpClient" factory-method="configureGlobalInstance" depends-on="appInfo">
<constructor-arg ref="httpClientConfig"/>
</bean>

View file

@ -90,6 +90,9 @@ wrapper.java.additional.4=-Dorg.apache.camel.jmx.disabled=true
# Enforces GMT to be used as the timezone
wrapper.java.additional.5=-Duser.timezone=GMT
# Set default tmp to awips controlled directory for security
wrapper.java.additional.6=-Djava.io.tmpdir=/awips2/tmp
# garbage collection settings
wrapper.java.additional.gc.1=-XX:+UseConcMarkSweepGC
wrapper.java.additional.gc.2=-XX:+CMSIncrementalMode

View file

@ -186,16 +186,6 @@
<fileset dir="${buildDirectory}/../../../rpms/legal/FOSS_licenses"/>
</zip>
<!-- Update the 32-bit win32 AlertViz zip with static files -->
<zip destfile="${buildDirectory}/${buildLabel}/${buildId}-win32.win32.x86.zip"
update="true">
<fileset dir="${buildDirectory}/../../static/win32.x86"
excludes="cave/**" />
<zipfileset dir="${buildDirectory}/../../../rpms/legal"
includes="Master_Rights_File.pdf" prefix="alertviz"/>
<zipfileset dir="/tmp/alertviz" includes="FOSS_licenses.zip" prefix="alertviz"/>
</zip>
<!-- Update the 64-bit (amd64) win32 CAVE zip with static files -->
<zip destfile="${buildDirectory}/${buildLabel}/${buildId}-win32.win32.x86_64.zip"
update="true">

View file

@ -69,6 +69,7 @@ java -jar $LAUNCHER_JAR -application org.eclipse.ant.core.antRunner \
-Dbuilder=$BUILDER \
-DbuildDirectory=${BUILDER}/tmp \
-Dbase=$BUILDER \
-DproductFile=awips.product \
$OPTS_FOR_ANT
rc=$?

View file

@ -7,6 +7,8 @@
value="gtk" />
<property name="build.arch"
value="x86" />
<property name="build.product"
value="awips.product" />
<!-- Copy the zip file that is produced to this location. -->
<property name="destination.dir"
value="" />
@ -71,6 +73,7 @@
<arg value="-DbuildDirectory=${basedir}/cave/tmp" />
<arg value="-Dbase=${basedir}/cave" />
<arg value="-Dconfigs=${build.os},${build.ws},${build.arch}" />
<arg value="-DproductFile=${build.product}" />
<classpath>
<pathelement
@ -128,4 +131,4 @@
<taskdef resource="net/sf/antcontrib/antlib.xml"
classpath="${basedir}/lib/ant/ant-contrib-1.0b3.jar" />
</project>
</project>

View file

@ -19,7 +19,10 @@
# them on the command line (e.g., -DbaseLocation=d:/eclipse
############# PRODUCT/PACKAGING CONTROL #############
product=${base}/../../com.raytheon.viz.product.awips/awips.product
# The product file is specified in the build.xml as a default and is
# overridable setting 'build.product' from ant.
product=${base}/../../com.raytheon.viz.product.awips/${productFile}
#product=${base}/../../com.raytheon.viz.product.awips/developer.product
runPackager=true

View file

@ -196,16 +196,6 @@
<fileset dir="${buildDirectory}/../../../rpms/legal/FOSS_licenses"/>
</zip>
<!-- Update the 32-bit win32 CAVE zip with static and license files -->
<zip destfile="${buildDirectory}/${buildLabel}/${buildId}-win32.win32.x86.zip"
update="true">
<fileset dir="${buildDirectory}/../../static/win32.x86"
excludes="alertviz/**" />
<zipfileset dir="${buildDirectory}/../../../rpms/legal"
includes="Master_Rights_File.pdf" prefix="cave"/>
<zipfileset dir="/tmp/cave" includes="FOSS_licenses.zip" prefix="cave"/>
</zip>
<!-- Update the 64-bit (amd64) win32 CAVE zip with static and license files -->
<zip destfile="${buildDirectory}/${buildLabel}/${buildId}-win32.win32.x86_64.zip"
update="true">

View file

@ -10,10 +10,8 @@ The following common directories exist within the static directory:
architecture.
We also have the following os / architecture specific directories within the static
directory. The name of the directories is based on the eclipse (3.6.1) os.arch
directory. The name of the directories is based on the eclipse (3.8.2) os.arch
designation.
linux.x86 - these files will only be installed on a 32-bit Linux Operating System.
linux.x86_64 - these files will only be installed on a 64-bit Linux Operating System.
win32.x86 - these files will only be installed on a 32-bit MS Windows Operating System.
win32.amd64 - these files will only be installed on a 64-bit Windows Operating System.
macosx.x86 - these files will only be installed on a 32-bit Apple OS X Operating System.

View file

@ -26,6 +26,7 @@
# Date Ticket# Engineer Description
# ------------ ---------- ----------- --------------------------
# Oct 09, 2014 #3675 bclement added cleanExit signal trap
# Jun 17, 2015 #4148 rferrel Logback needs fewer environment variables.
#
user=`/usr/bin/whoami`
@ -96,7 +97,7 @@ fi
#check for the logs directory, which may not be present at first start
hostName=`hostname -s`
LOGDIR=$HOME/caveData/logs/consoleLogs/$hostName/
export LOGDIR=$HOME/caveData/logs/consoleLogs/$hostName/
if [ ! -d $LOGDIR ]; then
mkdir -p $LOGDIR
@ -122,27 +123,17 @@ trap 'cleanExit $pid' SIGHUP SIGINT SIGQUIT SIGTERM
count=0
while [ $exitVal -ne 0 -a $count -lt 10 ]
do
count=`expr $count + 1`
curTime=`date +%Y%m%d_%H%M%S`
LOGFILE=${LOGDIR}/alertviz_${curTime}_console.log
export LOGFILE_ALERTVIZ=${LOGDIR}/alertviz_${curTime}_admin.log
#first check if we can write to the directory
if [ -w ${LOGDIR} ]; then
touch ${LOGFILE}
fi
#check for display; if no display then exit
if [ -z "${DISPLAY}" ]; then
echo "Display is not available."
exitVal=0
else
#finally check if we can write to the file
if [ -w ${LOGFILE} ]; then
${dir}/alertviz $* > ${LOGFILE} 2>&1 &
count=`expr $count + 1`
#check for display; if no display then exit
if [ -z "${DISPLAY}" ]; then
echo "Display is not available."
exitVal=0
else
${dir}/alertviz $* &
fi
if [ -w ${LOGDIR} ] ; then
${dir}/alertviz $* > /dev/null 2>&1 &
else
${dir}/alertviz $* &
fi
pid=$!
wait $pid
exitVal=$?

View file

@ -34,6 +34,7 @@
# Oct 10, 2014 #3675 njensen Logback now does console logging to ensure correct pid
# Oct 13, 2014 #3675 bclement startup shutdown log includes both launching pid and placeholder
# Jan 28, 2015 #4018 randerso Added a productEditor log file to changes in the GFE product editor
# Jun 17, 2015 #4148 rferrel Logback needs fewer environment variables.
#
@ -194,7 +195,7 @@ then
fi
BASE_LOGDIR=$HOME/caveData/logs/consoleLogs
LOGDIR=$BASE_LOGDIR/$hostName/
export LOGDIR=$BASE_LOGDIR/$hostName/
# make sure directory exists
if [ ! -d $LOGDIR ]; then
@ -212,13 +213,6 @@ export LOGFILE_STARTUP_SHUTDOWN="${LOGDIR}/${PROGRAM_NAME}_${pid}_${curTime}_pid
# At this point fork so that log files can be set up with the process pid and
# this process can log the exit status of cave.
(
# we include the PID of the launching process along with
# a %PID% placeholder to be replaced with the "real" PID
export LOGFILE_CAVE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_%PID%_logs.log"
export LOGFILE_CONSOLE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_%PID%_console.log"
export LOGFILE_PERFORMANCE="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_%PID%_perf.log"
export LOGFILE_PRODUCT_EDITOR="${LOGDIR}/${PROGRAM_NAME}_${curTime}_pid_%PID%_productEditor.log"
# can we write to log directory
if [ -w ${LOGDIR} ]; then
touch ${LOGFILE_STARTUP_SHUTDOWN}

View file

@ -1,52 +0,0 @@
@echo OFF
REM Determine where we are located.
SET CONTAINING_DIRECTORY=%~dp0
REM Prepare the environment.
REM Location of AWIPS II Java (the jre).
SET JavaJreDirectory=C:\Program Files\Raytheon\AWIPS II\Java\jre7
REM Location of AWIPS II Python.
SET PythonInstallDirectory=C:\Program Files\Raytheon\AWIPS II\Python
REM Add Java and Python to the path.
SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path%
SET Path=%JavaJreDirectory%\bin;%Path%
REM Define 'PythonPath'.
SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%;%PythonPath%
REM Eliminate variables that will no longer be used.
SET PythonInstallDirectory=
SET JavaJreDirectory=
REM Determine where we will be logging to.
SET HOME_DIRECTORY=%USERPROFILE%
SET CAVEDATA_LOG_DIRECTORY=%HOME_DIRECTORY%\caveData\logs
SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME%
IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%")
echo Starting ALERTVIZ; leave this CMD window open to enable AlertViz 'restart'.
REM Start AlertViz (and implement the alertviz restart capability).
:AlertVizLoopStart
SET RND=%random%
SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp
REM Python is used to retrieve the current date and time because the order
REM of the Windows date/time fields is not necessarily guaranteed and the
REM Windows date/time fields can only be extracted using substring operations
REM instead of -formatter- strings like Linux allows.
python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE%
SET /p LOG_DATETIME= < %RND_DATETIME_FILE%
DEL %RND_DATETIME_FILE%
SET LOGFILE_CONSOLE=%CAVEDATA_LOG_DIRECTORY%\alertviz_%LOG_DATETIME%_console.log
SET LOGFILE_ALERTVIZ=%CAVEDATA_LOG_DIRECTORY%\alertviz_%LOG_DATETIME%_admin.log
"%CONTAINING_DIRECTORY%alertviz.exe" %* > "%CONSOLE_LOG_DIRECTORY%\alertviz_%LOG_DATETIME%.log" 2>&1
IF %ERRORLEVEL% == 0 (EXIT)
echo Restarting AlertViz.
GOTO AlertVizLoopStart

View file

@ -1,56 +0,0 @@
@echo OFF
REM Determine where we are located.
SET CONTAINING_DIRECTORY=%~dp0
REM Prepare the environment.
REM Location of AWIPS II Java (the jre).
SET JavaJreDirectory=C:\Program Files\Raytheon\AWIPS II\Java\jre7
REM Location of AWIPS II Python.
SET PythonInstallDirectory=C:\Program Files\Raytheon\AWIPS II\Python
REM Add Java and Python to the path.
SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path%
SET Path=%JavaJreDirectory%\bin;%Path%
REM Add the CAVE lib directory to the path.
SET Path=%CONTAINING_DIRECTORY%lib;%Path%
REM Define 'PythonPath'.
SET PythonPath=%CONTAINING_DIRECTORY%lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%;%PythonPath%
REM Eliminate variables that will no longer be used.
SET PythonInstallDirectory=
SET JavaJreDirectory=
REM Determine where we will be logging to.
SET HOME_DIRECTORY=%USERPROFILE%
SET CAVEDATA_LOG_DIRECTORY=%HOME_DIRECTORY%\caveData\logs
SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME%
IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%")
SET RND=%random%
SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp
REM Python is used to retrieve the current date and time because the order
REM of the Windows date/time fields is not necessarily guaranteed and the
REM Windows date/time fields can only be extracted using substring operations
REM instead of -formatter- strings like Linux allows.
python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE%
SET /p LOG_DATETIME= < %RND_DATETIME_FILE%
DEL %RND_DATETIME_FILE%
SET LOGFILE_CAVE=%CAVEDATA_LOG_DIRECTORY%\cave_%LOG_DATETIME%_logs.log
SET LOGFILE_CONSOLE=%CAVEDATA_LOG_DIRECTORY%\cave_%LOG_DATETIME%_console.log
SET LOGFILE_PERFORMANCE=%CAVEDATA_LOG_DIRECTORY%\cave_%LOG_DATETIME%_perf.log
SET LOGFILE_PRODUCT_EDITOR=%CAVEDATA_LOG_DIRECTORY%\cave_%LOG_DATETIME%_productEditor.log
echo THIS CMD WINDOW CAN BE CLOSED AT ANY TIME!
cd %HOMEPATH%
REM Start CAVE.
"%CONTAINING_DIRECTORY%cave.exe" %* > "%CONSOLE_LOG_DIRECTORY%\cave_%LOG_DATETIME%.log" 2>&1
IF ERRORLEVEL 1 (echo CAVE ERROR - check the logs for additional information. && PAUSE)
EXIT

View file

@ -1,69 +0,0 @@
@echo OFF
REM Determine if we are running on a 32-bit or 64-bit OS.
IF NOT EXIST C:\Windows\SysWOW64\reg.exe (
SET REG_EXE=C:\Windows\System32\reg.exe
) ELSE (
SET REG_EXE=C:\Windows\SysWOW64\reg.exe
)
REM Determine where we are located.
SET CONTAINING_DIRECTORY=%~dp0
REM Prepare the environment.
REM Registry Query Variables.
SET A2_JAVA_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Java"
SET A2_PYTHON_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Python"
REM Determine where AWIPS II Java (the jre) is located.
%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Java. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory') DO (
SET JavaJreDirectory=%%B)
REM Determine where AWIPS II Python is located.
%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Python. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory') DO (
SET PythonInstallDirectory=%%B)
REM Add Java and Python to the path.
SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path%
SET Path=%JavaJreDirectory%\bin;%Path%
REM Define 'PythonPath'.
SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%;%PythonPath%
REM Eliminate variables that will no longer be used.
SET PythonInstallDirectory=
SET JavaJreDirectory=
SET REG_EXE=
SET A2_JAVA_REG=
SET A2_PYTHON_REG=
REM Determine where we will be logging to.
SET HOME_DIRECTORY=%HOMEDRIVE%%HOMEPATH%
SET CAVEDATA_LOG_DIRECTORY=%HOMEDRIVE%%HOMEPATH%\caveData\logs
SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME%
IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%")
echo Starting ALERTVIZ; leave this CMD window open to enable AlertViz 'restart'.
REM Start AlertViz (and implement the alertviz restart capability).
:AlertVizLoopStart
SET RND=%random%
SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp
REM Python is used to retrieve the current date and time because the order
REM of the Windows date/time fields is not necessarily guaranteed and the
REM Windows date/time fields can only be extracted using substring operations
REM instead of -formatter- strings like Linux allows.
python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE%
SET /p LOG_DATETIME= < %RND_DATETIME_FILE%
DEL %RND_DATETIME_FILE%
"%CONTAINING_DIRECTORY%alertviz.exe" %* > "%CONSOLE_LOG_DIRECTORY%\alertviz_%LOG_DATETIME%.log" 2>&1
IF %ERRORLEVEL% == 0 (EXIT)
echo Restarting AlertViz.
GOTO AlertVizLoopStart

View file

@ -1,72 +0,0 @@
@echo OFF
REM Determine if we are running on a 32-bit or 64-bit OS.
IF NOT EXIST C:\Windows\SysWOW64\reg.exe (
SET REG_EXE=C:\Windows\System32\reg.exe
) ELSE (
SET REG_EXE=C:\Windows\SysWOW64\reg.exe
)
REM Determine where we are located.
SET CONTAINING_DIRECTORY=%~dp0
REM Prepare the environment.
REM Registry Query Variables.
SET A2_JAVA_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Java"
SET A2_PYTHON_REG="HKLM\Software\Raytheon\Runtime Environment\AWIPS II Python"
REM Determine where AWIPS II Java (the jre) is located.
%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Java. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_JAVA_REG% /v JavaJreDirectory') DO (
SET JavaJreDirectory=%%B)
REM Determine where AWIPS II Python is located.
%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory > NUL 2>&1
IF ERRORLEVEL 1 (echo ENVIRONMENT ERROR - Unable to find AWIPS II Python. && PAUSE && EXIT)
FOR /F "tokens=2* delims= " %%A IN (
'%REG_EXE% QUERY %A2_PYTHON_REG% /v PythonInstallDirectory') DO (
SET PythonInstallDirectory=%%B)
REM Add Java and Python to the path.
SET Path=%PythonInstallDirectory%;%PythonInstallDirectory%\DLLs;%Path%
SET Path=%JavaJreDirectory%\bin;%Path%
REM Add the CAVE lib directory to the path.
SET Path=%CONTAINING_DIRECTORY%lib;%Path%
REM Define 'PythonPath'.
SET PythonPath=%CONTAINING_DIRECTORY%lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib\lib-tk;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\DLLs;%PythonPath%
SET PythonPath=%PythonInstallDirectory%\Lib;%PythonPath%
SET PythonPath=%PythonInstallDirectory%;%PythonPath%
REM Eliminate variables that will no longer be used.
SET PythonInstallDirectory=
SET JavaJreDirectory=
SET REG_EXE=
SET A2_JAVA_REG=
SET A2_PYTHON_REG=
REM Determine where we will be logging to.
SET HOME_DIRECTORY=%HOMEDRIVE%%HOMEPATH%
SET CAVEDATA_LOG_DIRECTORY=%HOMEDRIVE%%HOMEPATH%\caveData\logs
SET CONSOLE_LOG_DIRECTORY=%CAVEDATA_LOG_DIRECTORY%\consoleLogs\%COMPUTERNAME%
IF NOT EXIST "%CONSOLE_LOG_DIRECTORY%" (MKDIR "%CONSOLE_LOG_DIRECTORY%")
SET RND=%random%
SET RND_DATETIME_FILE=%TMP%\awips2dt_%RND%.tmp
REM Python is used to retrieve the current date and time because the order
REM of the Windows date/time fields is not necessarily guaranteed and the
REM Windows date/time fields can only be extracted using substring operations
REM instead of -formatter- strings like Linux allows.
python -c "from datetime import datetime; print datetime.now().strftime('%%Y%%m%%d_%%H%%M%%S');" > %RND_DATETIME_FILE%
SET /p LOG_DATETIME= < %RND_DATETIME_FILE%
DEL %RND_DATETIME_FILE%
echo THIS CMD WINDOW CAN BE CLOSED AT ANY TIME!
cd %HOMEPATH%
REM Start CAVE.
"%CONTAINING_DIRECTORY%cave.exe" %* > "%CONSOLE_LOG_DIRECTORY%\cave_%LOG_DATETIME%.log" 2>&1
IF ERRORLEVEL 1 (echo CAVE ERROR - check the logs for additional information. && PAUSE)
EXIT

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.viz.alertview.feature</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.pde.FeatureBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.FeatureNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1 @@
bin.includes = feature.xml

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<feature
id="com.raytheon.uf.viz.alertview.feature"
label="AlertView Feature"
version="1.0.0.qualifier"
provider-name="RAYTHEON">
<description url="http://www.example.com/description">
[Enter Feature Description here.]
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<requires>
<import feature="com.raytheon.uf.common.base.feature" version="1.0.0.qualifier"/>
</requires>
<plugin
id="com.raytheon.uf.viz.alertview"
download-size="0"
install-size="0"
version="0.0.0"/>
<plugin
id="com.raytheon.uf.viz.alertview.logback"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.viz.alertview.localization"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.viz.alertview.localization</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,12 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: AlertView Localization
Bundle-SymbolicName: com.raytheon.uf.viz.alertview.localization
Bundle-Version: 1.15.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Require-Bundle: com.raytheon.uf.common.localization;bundle-version="1.14.1",
com.raytheon.uf.viz.alertview;bundle-version="1.15.0"
Service-Component: OSGI-INF/*.xml

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="com.raytheon.uf.viz.alertview.localization.AlertViewLocalizationPrefStore" enabled="true" xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="com.raytheon.uf.viz.alertview.localization.AlertViewLocalizationPrefStore" />
<service>
<provide interface="com.raytheon.uf.viz.alertview.AlertViewPrefStore" />
</service>
<property name="service.ranking" type="Integer" value="100"/>
<reference name="PathManager"
bind="setPathManager"
unbind="unsetPathManager"
interface="com.raytheon.uf.common.localization.IPathManager"
cardinality="1..1"
policy="static" />
</component>

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
OSGI-INF/

View file

@ -0,0 +1,170 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.localization;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import com.raytheon.uf.common.localization.FileUpdatedMessage;
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.LocalizationFileOutputStream;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException;
import com.raytheon.uf.viz.alertview.AlertViewPrefStore;
/**
*
* An {@link AlertViewPrefStore} that stores preferences in
* {@link LocalizationFile}s.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 26, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertViewLocalizationPrefStore implements AlertViewPrefStore,
ILocalizationFileObserver {
private static final String BASE_PATH = "alertView"
+ IPathManager.SEPARATOR;
private final Set<AlertViewPrefListener> listeners = new CopyOnWriteArraySet<>();
private IPathManager pathManager;
protected LocalizationFile getRootFile() {
LocalizationContext context = pathManager.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.BASE);
return pathManager.getLocalizationFile(context, BASE_PATH);
}
public void setPathManager(IPathManager pathManager) {
this.pathManager = pathManager;
getRootFile().addFileUpdatedObserver(this);
}
public void unsetPathManager(IPathManager pathManager) {
if (pathManager == this.pathManager) {
getRootFile().removeFileUpdatedObserver(this);
this.pathManager = null;
}
}
@Override
public InputStream readConfigFile(String fileName) throws IOException {
LocalizationFile file = pathManager.getStaticLocalizationFile(
LocalizationType.COMMON_STATIC, BASE_PATH + fileName);
if (file == null) {
return null;
} else {
try {
return file.openInputStream();
} catch (LocalizationException e) {
throw new IOException(e);
}
}
}
@Override
public OutputStream writeConfigFile(String fileName) throws IOException {
LocalizationContext context = pathManager.getContext(
LocalizationType.COMMON_STATIC, LocalizationLevel.USER);
LocalizationFile file = pathManager.getLocalizationFile(context,
BASE_PATH + fileName);
if (file == null) {
return null;
} else {
try {
return new SavingOutputStream(file.openOutputStream());
} catch (LocalizationException e) {
throw new IOException(e);
}
}
}
@Override
public void addListener(AlertViewPrefListener listener) {
listeners.remove(listener);
}
@Override
public void removeListener(AlertViewPrefListener listener) {
listeners.add(listener);
}
@Override
public void fileUpdated(FileUpdatedMessage message) {
String fileName = message.getFileName().substring(BASE_PATH.length());
for (AlertViewPrefListener listener : listeners) {
listener.prefFileChanged(fileName);
}
}
private class SavingOutputStream extends OutputStream {
private final LocalizationFileOutputStream stream;
public SavingOutputStream(LocalizationFileOutputStream stream) {
this.stream = stream;
}
@Override
public void close() throws IOException {
try {
stream.closeAndSave();
} catch (LocalizationOpFailedException e) {
throw new IOException(e);
}
}
@Override
public void write(int b) throws IOException {
stream.write(b);
}
@Override
public void write(byte[] b) throws IOException {
stream.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
stream.write(b, off, len);
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.viz.alertview.logback</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,14 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: LogBack AlertView compatibility
Bundle-SymbolicName: com.raytheon.uf.viz.alertview.logback
Bundle-Version: 1.15.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Eclipse-RegisterBuddy: ch.qos.logback
Require-Bundle: ch.qos.logback;bundle-version="1.1.2",
com.raytheon.uf.viz.alertview;bundle-version="1.15.0",
org.slf4j;bundle-version="1.7.5"
Import-Package: org.osgi.framework;version="1.7.0",
org.osgi.util.tracker;version="1.5.1"
Bundle-ActivationPolicy: lazy

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,118 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.logback;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.util.tracker.ServiceTracker;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.Layout;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.AlertDestination;
/**
*
* An {@link Appender} that converts {@link ILoggingEvent}s to {@link Alert}s
* and sends them to all registered {@link AlertDestination}s. The
* {@link Appender} can be configured with a {@link Layout} to provide custom
* details in the alert, if no layout is provided the default layout is just the
* exception with a full stack trace.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 16, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertViewAppender extends AppenderBase<ILoggingEvent> {
protected Layout<ILoggingEvent> layout;
private transient ServiceTracker<AlertDestination, AlertDestination> destinationTracker;
@Override
protected void append(ILoggingEvent event) {
AlertDestination[] destinations = destinationTracker
.getServices(new AlertDestination[0]);
if(destinations == null || destinations.length == 0){
return;
}
Alert alert = new LoggingEventAlert(layout, event);
for (AlertDestination destination : destinations) {
destination.handleAlert(alert);
}
}
@Override
public void start() {
Bundle bundle = FrameworkUtil.getBundle(getClass());
BundleContext context = bundle.getBundleContext();
context.addBundleListener(new AppenderBundleListener(bundle, this));
destinationTracker = new ServiceTracker<>(context, AlertDestination.class,
null);
destinationTracker.open();
if (layout == null) {
PatternLayout patternLayout = new PatternLayout();
patternLayout.setContext(this.context);
patternLayout.setPattern("%ex");
layout = patternLayout;
}
layout.start();
super.start();
}
@Override
public void stop() {
super.stop();
layout.stop();
if (destinationTracker != null) {
destinationTracker.close();
destinationTracker = null;
}
}
@Override
public boolean isStarted() {
if (super.isStarted()) {
return destinationTracker != null;
} else {
return false;
}
}
public void setLayout(Layout<ILoggingEvent> layout) {
this.layout = layout;
}
}

View file

@ -0,0 +1,63 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.logback;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.SynchronousBundleListener;
/**
*
* A {@link BundleListener} that is used by the {@link AlertViewAppender} to
* ensure that when the bundle stops the appender is also stopped.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 24, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AppenderBundleListener implements SynchronousBundleListener {
private final Bundle bundle;
private final AlertViewAppender appender;
public AppenderBundleListener(Bundle bundle, AlertViewAppender appender) {
this.bundle = bundle;
this.appender = appender;
}
@Override
public void bundleChanged(BundleEvent event) {
if (event.getType() == BundleEvent.STOPPING
&& event.getBundle() == bundle) {
appender.stop();
}
}
}

View file

@ -0,0 +1,92 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.logback;
import java.util.Date;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Layout;
import com.raytheon.uf.viz.alertview.Alert;
/**
*
* Wraps an {@link ILoggingEvent} in the {@link Alert} interface so it can be
* added to the AlertView.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 16, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class LoggingEventAlert implements Alert {
private final Layout<ILoggingEvent> layout;
private final ILoggingEvent event;
public LoggingEventAlert(Layout<ILoggingEvent> layout, ILoggingEvent event) {
this.layout = layout;
this.event = event;
}
@Override
public Date getTime() {
return new Date(event.getTimeStamp());
}
@Override
public Priority getPriority() {
if (event.getLevel() == Level.ERROR) {
return Priority.ERROR;
} else if (event.getLevel() == Level.WARN) {
return Priority.WARN;
} else if (event.getLevel() == Level.INFO) {
return Priority.INFO;
} else {
return Priority.DEBUG;
}
}
@Override
public String getOrigin() {
return event.getLoggerName();
}
@Override
public String getMessage() {
return event.getFormattedMessage();
}
@Override
public String getDetails() {
return layout.doLayout(event);
}
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.viz.alertview</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,18 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: AlertView
Bundle-SymbolicName: com.raytheon.uf.viz.alertview;singleton:=true
Bundle-Version: 1.15.0.qualifier
Bundle-Vendor: RAYTHEON
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: com.raytheon.uf.viz.alertview
Require-Bundle: org.eclipse.ui;bundle-version="3.8.2",
org.eclipse.core.runtime;bundle-version="3.8.0",
org.eclipse.jface.text;bundle-version="3.8.2",
org.eclipse.ui.console;bundle-version="3.5.100",
org.slf4j;bundle-version="1.7.5"
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: com.raytheon.uf.viz.alertview.jar
Service-Component: OSGI-INF/*.xml
Bundle-Activator: com.raytheon.uf.viz.alertview.AlertViewActivator

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="com.raytheon.uf.viz.alertview.ui.view.AlertViewAutoOpen" enabled="true" xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="com.raytheon.uf.viz.alertview.ui.view.AlertViewAutoOpen" />
<service>
<provide interface="com.raytheon.uf.viz.alertview.AlertDestination" />
</service>
</component>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="com.raytheon.uf.viz.alertview.ui.popup.AlertPopup" enabled="true" xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="com.raytheon.uf.viz.alertview.ui.popup.AlertPopup" />
<service>
<provide interface="com.raytheon.uf.viz.alertview.AlertDestination" />
</service>
</component>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="com.raytheon.uf.viz.alertview.prefs.RCPPrefStore" enabled="true" xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="com.raytheon.uf.viz.alertview.prefs.RCPPrefStore" />
<service>
<provide interface="com.raytheon.uf.viz.alertview.AlertViewPrefStore" />
</service>
</component>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<component name="com.raytheon.uf.viz.alertview.store.MemoryAlertStore" enabled="true" xmlns="http://www.osgi.org/xmlns/scr/v1.1.0">
<implementation class="com.raytheon.uf.viz.alertview.store.MemoryAlertStore" />
<service>
<provide interface="com.raytheon.uf.viz.alertview.AlertDestination" />
<provide interface="com.raytheon.uf.viz.alertview.AlertStore" />
</service>
</component>

View file

@ -0,0 +1,9 @@
jars.compile.order = com.raytheon.uf.viz.alertview.jar
source.com.raytheon.uf.viz.alertview.jar = src/
output.com.raytheon.uf.viz.alertview.jar = bin/
bin.includes = META-INF/,\
OSGI-INF/,\
icons/,\
plugin.xml,\
defaultPrefs/,\
com.raytheon.uf.viz.alertview.jar

View file

@ -0,0 +1,7 @@
<popUpPreferences>
<filter>error</filter>
<duration>3000</duration>
<width>500</width>
<height>50</height>
<corner>LOWER_RIGHT</corner>
</popUpPreferences>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<styleList>
<style>
<filter>error</filter>
<foregroundColor>#FF0000</foregroundColor>
</style>
</styleList>

View file

@ -0,0 +1,21 @@
<popUpPreferences>
<openFilter>none</openFilter>
<activeFilter>warnPlus</activeFilter>
<filterMenu>
<filter>all</filter>
<text>All</text>
</filterMenu>
<filterMenu>
<filter>error</filter>
<text>Only Errors</text>
</filterMenu>
<filterMenu>
<filter>warnPlus</filter>
<text>Errors and Warnings</text>
</filterMenu>
<column>Time</column>
<column>Priority</column>
<column>Message</column>
<alertsToLoad>1000</alertsToLoad>
<mergeRepeatInterval>1000</mergeRepeatInterval>
</popUpPreferences>

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
<extension
point="org.eclipse.ui.views">
<view
allowMultiple="false"
category="com.raytheon.viz.ui"
class="com.raytheon.uf.viz.alertview.ui.view.AlertView"
icon="icons/alertView.png"
id="com.raytheon.uf.viz.alertview.ui.view.AlertView"
name="Alert View"
restorable="true"/>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
locationURI="menu:CAVE?after=browsers">
<command
commandId="com.raytheon.uf.viz.alertview.openAlertView"
label="Open AlertView"
style="push">
<visibleWhen>
<systemTest property="alertview.enabled" value="true" />
</visibleWhen>
</command>
</menuContribution>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.raytheon.uf.viz.alertview.ui.view.OpenAlertViewHandler"
commandId="com.raytheon.uf.viz.alertview.openAlertView">
</handler>
</extension>
<extension
point="org.eclipse.ui.commands">
<command
id="com.raytheon.uf.viz.alertview.openAlertView"
name="Open AlertView">
</command>
</extension>
</plugin>

View file

@ -0,0 +1,77 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview;
import java.util.Date;
import com.raytheon.uf.viz.alertview.ui.view.AlertView;
/**
* The primary interface for items that should be displayed in {@link AlertView}
* .
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public interface Alert {
public enum Priority {
DEBUG, INFO, WARN, ERROR;
}
/**
* @return The time the event occured that generated this alert.
*/
public Date getTime();
/**
* @return The importance of the alert.
*/
public Priority getPriority();
/**
* @return An arbitrary string describing the origin of the Alert. This
* should be a short word or phrase that can be used by the user to
* take special action based on origins that are more or less
* important for a specific user.
*/
public String getOrigin();
/**
* @return A short summary of the alert.
*/
public String getMessage();
/**
* @return A detailed description of the alert.
*/
public String getDetails();
}

View file

@ -0,0 +1,47 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview;
/**
*
* An OSGi service interface for any service component that needs to know about
* {@link Alert}s. Any component which wants to contribute new alerts should
* broadcast the Alert to all registered {@link AlertDestination}s. Any
* componenet that needs to know about new Alerts should implement this
* interface and register as a service.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public interface AlertDestination {
public void handleAlert(Alert alert);
}

View file

@ -0,0 +1,50 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview;
import java.util.List;
/**
*
* An OSGi service interface that provides a way for the AlertView to load
* {@link Alert}s that arrive while it is not open. At a minimum a store should
* be accumulating new messages as they arrive. A store may want to provide
* persistant storage so that old alerts can be viewed from a new cave.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public interface AlertStore {
/**
* @return All stored alerts.
*/
public List<Alert> getAlerts();
}

View file

@ -0,0 +1,136 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.preference.PreferenceNode;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import com.raytheon.uf.viz.alertview.ui.prefs.AlertViewPreferencePage;
import com.raytheon.uf.viz.alertview.ui.prefs.PopupPreferencePage;
import com.raytheon.uf.viz.alertview.ui.prefs.StylePreferencePage;
/**
*
* {@link BundleActivator} that is used to only show the preference pages if
* AlertView is being used.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 30, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertViewActivator implements BundleActivator {
@Override
public void start(BundleContext context) throws InvalidSyntaxException {
/*
* Only show the preferences if this bundle is activated which will
* happen through declarative services if anyone is using the
* destination.
*/
if (PlatformUI.isWorkbenchRunning()) {
addPreferencePages();
} else {
String workbenchFilter = "(" + Constants.OBJECTCLASS + "="
+ IWorkbench.class.getName() + ")";
context.addServiceListener(new ServiceListener() {
@Override
public void serviceChanged(ServiceEvent event) {
if (event.getType() == ServiceEvent.REGISTERED) {
addPreferencePages();
}
}
}, workbenchFilter);
}
}
protected void addPreferencePages() {
PreferenceManager pm = PlatformUI.getWorkbench().getPreferenceManager();
PreferenceNode alertViewNode = new PreferenceNode(
AlertViewPreferencePage.class.getName(), "Alert View", null,
null) {
@Override
public void createPage() {
AlertViewPreferencePage page = new AlertViewPreferencePage();
page.setTitle(getLabelText());
page.setDescription("Configure AlertView appearance and behavior.");
setPage(page);
}
};
PreferenceNode popUpNode = new PreferenceNode(
PopupPreferencePage.class.getName(), "Popup", null, null) {
@Override
public void createPage() {
PopupPreferencePage page = new PopupPreferencePage();
page.setTitle(getLabelText());
page.setDescription("Configure Alert Popup appearance and behavior.");
setPage(page);
}
};
PreferenceNode styleNode = new PreferenceNode(
StylePreferencePage.class.getName(), "Style", null, null) {
@Override
public void createPage() {
StylePreferencePage page = new StylePreferencePage();
page.setTitle(getLabelText());
page.setDescription("Configure the way alerts appear in the alert table.");
setPage(page);
}
};
alertViewNode.add(popUpNode);
alertViewNode.add(styleNode);
pm.addToRoot(alertViewNode);
}
@Override
public void stop(BundleContext context) throws Exception {
if (PlatformUI.isWorkbenchRunning()) {
PreferenceManager pm = PlatformUI.getWorkbench()
.getPreferenceManager();
pm.remove(AlertViewPreferencePage.class.getName());
}
}
}

View file

@ -0,0 +1,60 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
*
* An OSGi service interface that supplies configuration information to
* AlertView components.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public interface AlertViewPrefStore {
public InputStream readConfigFile(String fileName) throws IOException;
public OutputStream writeConfigFile(String fileName) throws IOException;
public void addListener(AlertViewPrefListener listener);
public void removeListener(AlertViewPrefListener listener);
public static interface AlertViewPrefListener {
public void prefFileChanged(String fileName);
}
}

View file

@ -0,0 +1,215 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.action;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.eclipse.jface.action.Action;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.PlatformUI;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.Alert.Priority;
import com.raytheon.uf.viz.alertview.ui.view.AlertView;
/**
*
* Action for writing an alert to a file.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 24, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class SaveToFileAction extends Action {
private static final Charset UTF8 = Charset.forName("UTF-8");
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss,SSS");
/** Don't waste memory keeping excessive details. */
private static final int MAX_DETAILS_SIZE = 16 * 1024;
private static Logger logger = LoggerFactory.getLogger(AlertView.class);
private final Alert alert;
private final Path path;
public SaveToFileAction(Alert alert) {
super("Save to file...");
this.alert = alert;
this.path = null;
}
public SaveToFileAction(Alert alert, Path path) {
super("Save to file...");
this.alert = alert;
this.path = path;
}
@Override
public void run() {
Path path = this.path;
if (path == null) {
FileDialog fd = new FileDialog(PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getShell(), SWT.SAVE);
fd.setFileName("alert.txt");
fd.setFilterExtensions(new String[] { "*.txt" });
String fileName = fd.open();
if (fileName != null) {
path = Paths.get(fileName);
} else {
return;
}
}
try {
write(path, alert);
} catch (IOException e) {
logger.error("Unable to save alert", e);
}
}
public static void write(Path path, Alert alert) throws IOException {
Bundle bundle = FrameworkUtil.getBundle(SaveToFileAction.class);
try (BufferedWriter writer = Files.newBufferedWriter(path, UTF8)) {
writer.write("# Written by " + bundle.getSymbolicName() + " "
+ bundle.getVersion() + "\n");
writer.write(alert.getPriority().toString());
writer.write(" ");
writer.write(TIME_FORMAT.format(alert.getTime()));
writer.write(" ");
writer.write(alert.getMessage());
writer.write("\n");
writer.write(alert.getDetails());
}
}
public static Alert read(Path path) throws IOException {
byte[] bytes = Files.readAllBytes(path);
String content = new String(bytes, UTF8);
String first = "#";
String details = content;
while (first.startsWith("#")) {
String[] split = details.split("\n", 2);
if (split.length != 2) {
throw new IOException(path.toString()
+ " is not a valid alert file");
}
first = split[0];
details = split[1];
}
String[] split = first.split(" ", 4);
if (split.length != 4) {
throw new IOException(path.toString()
+ " is not a valid alert file");
}
Priority priority;
try {
priority = Priority.valueOf(split[0]);
} catch (IllegalArgumentException e) {
throw new IOException(split[0] + " is not a valid priority.");
}
Date time;
try {
time = TIME_FORMAT.parse(split[1] + " " + split[2]);
} catch (ParseException e) {
throw new IOException(path.toString()
+ " is not a valid alert file", e);
}
String message = split[3];
if (details.length() > MAX_DETAILS_SIZE) {
details = details.substring(0, MAX_DETAILS_SIZE)
+ "\n...file content truncated...";
}
return new ParsedAlert(priority, time, path.toString(), message,
details);
}
private static class ParsedAlert implements Alert {
private final Priority priority;
private final Date time;
private final String origin;
private final String message;
private final String details;
public ParsedAlert(Priority priority, Date time, String origin,
String message, String details) {
this.priority = priority;
this.time = time;
this.origin = origin;
this.message = message;
this.details = details;
}
@Override
public Date getTime() {
return time;
}
@Override
public Priority getPriority() {
return priority;
}
@Override
public String getOrigin() {
return origin;
}
@Override
public String getMessage() {
return message;
}
@Override
public String getDetails() {
return details;
}
}
}

View file

@ -0,0 +1,45 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.filter;
import com.raytheon.uf.viz.alertview.Alert;
/**
*
* Interface for an object that filters {@link Alert}s. This is used throughout
* alertview to ensure the user can see only alerts they are interested in.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public interface AlertFilter {
public boolean filter(Alert alert);
}

View file

@ -0,0 +1,55 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.filter;
import com.raytheon.uf.viz.alertview.Alert;
/**
* An {@link AlertFilter} that always returns true, or always returns false,
* ignoring the {@link Alert} that is passed in. This is used to implement a
* filter that either always accepts or always rejects Alerts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class ConstantFilter implements AlertFilter {
public final boolean result;
public ConstantFilter(boolean result) {
this.result = result;
}
@Override
public boolean filter(Alert alert) {
return result;
}
}

View file

@ -0,0 +1,99 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.filter;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.viz.alertview.Alert.Priority;
/**
*
* Provides a lookup mechanism for getting {@link AlertFilter}s using an id.
* This is especially useful when a filter is stored in a preference file
* because the id provides a convenient representation to store it and the
* manager provides a reliable way to lookup filters.
*
* TODO the current implementation just uses a small set of hard-coded filters.
* This should be implemented so that new filters can be added by other plugins
* and possibly even allow user defined filters to do things like regex the
* message.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class FilterManager {
/** Name for a filter that accepts all alerts. */
public static final String ALL = "all";
/** Name for a filter that accepts no alerts. */
public static final String NONE = "none";
/** Name for a filter that accepts alerts with priority >= WARN. */
public static final String WARN_PLUS = "warnPlus";
/** Name for a filter that accepts alerts with priority >= INFO. */
public static final String INFO_PLUS = "infoPlus";
private static Logger logger = LoggerFactory.getLogger(FilterManager.class);
private static final AlertFilter NONE_FILTER = new ConstantFilter(false);
private final Map<String, AlertFilter> filters = new HashMap<>();
public FilterManager() {
loadDefaultFilters();
}
private void loadDefaultFilters() {
filters.put(ALL, new ConstantFilter(true));
filters.put(NONE, new ConstantFilter(false));
for (Priority p : Priority.values()) {
filters.put(p.name().toLowerCase(), new PriorityFilter(p));
}
filters.put(WARN_PLUS, new MinPriorityFilter(Priority.WARN));
filters.put(INFO_PLUS, new MinPriorityFilter(Priority.INFO));
}
public AlertFilter getFilter(String id) {
AlertFilter filter = filters.get(id);
if (filter == null) {
logger.warn("AlertView FilterManager failed to find a filter with an id of "
+ id);
filter = NONE_FILTER;
}
return filter;
}
}

View file

@ -0,0 +1,55 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.filter;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.Alert.Priority;
/**
* An {@link AlertFilter} that returns true for {@link Alert}s that have a
* priority equal to or above a specified level.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class MinPriorityFilter implements AlertFilter {
private final Priority priority;
public MinPriorityFilter(Priority priority) {
this.priority = priority;
}
@Override
public boolean filter(Alert alert) {
return alert.getPriority().ordinal() >= priority.ordinal();
}
}

View file

@ -0,0 +1,55 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.filter;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.Alert.Priority;
/**
* An {@link AlertFilter} that returns true for {@link Alert}s that have a
* priority equal to a specified level.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class PriorityFilter implements AlertFilter {
private final Priority priority;
public PriorityFilter(Priority priority) {
this.priority = priority;
}
@Override
public boolean filter(Alert alert) {
return alert.getPriority() == priority;
}
}

View file

@ -0,0 +1,269 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.prefs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.viz.alertview.Alert.Priority;
import com.raytheon.uf.viz.alertview.filter.FilterManager;
import com.raytheon.uf.viz.alertview.ui.view.AlertTable;
import com.raytheon.uf.viz.alertview.ui.view.AlertView;
/**
* Contains the preferences that control how {@link AlertView} appears to the
* user.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
@XmlRootElement
public class AlertViewPreferences {
private final List<FilterMenu> DEFAULT_FILTERS = Arrays.asList(
new FilterMenu("All", FilterManager.ALL), new FilterMenu(
"Only Errors", Priority.ERROR.name().toLowerCase()),
new FilterMenu("Errors + Warnings", FilterManager.WARN_PLUS));
private final List<String> DEFAULT_COLUMNS = Arrays.asList(
AlertTable.COLUMN_TIME, AlertTable.COLUMN_PRIORITY,
AlertTable.COLUMN_MESSAGE);
private String openFilter;
private String activeFilter;
private List<FilterMenu> filterMenu;
private List<String> columns;
private int alertsToLoad;
/* Time in ms */
private int mergeRepeatInterval;
public AlertViewPreferences() {
/* Everything needs reasonable defaults to keep PreferenceFile happy. */
openFilter = FilterManager.NONE;
activeFilter = FilterManager.WARN_PLUS;
filterMenu = new ArrayList<>(DEFAULT_FILTERS);
columns = new ArrayList<>(DEFAULT_COLUMNS);
alertsToLoad = 1000;
mergeRepeatInterval = 1000;
}
public AlertViewPreferences(AlertViewPreferences other) {
this.openFilter = other.getOpenFilter();
this.activeFilter = other.getActiveFilter();
this.filterMenu = other.getFilterMenu();
this.columns = other.getColumns();
this.alertsToLoad = other.getAlertsToLoad();
this.mergeRepeatInterval = other.getMergeRepeatInterval();
}
public String getOpenFilter() {
return openFilter;
}
public void setOpenFilter(String openFilter) {
this.openFilter = openFilter;
}
public String getActiveFilter() {
return activeFilter;
}
public void setActiveFilter(String activeFilter) {
this.activeFilter = activeFilter;
}
public List<FilterMenu> getFilterMenu() {
return filterMenu;
}
public void setFilterMenu(List<FilterMenu> filterMenu) {
this.filterMenu = filterMenu;
}
public int getAlertsToLoad() {
return alertsToLoad;
}
public void setAlertsToLoad(int alertsToLoad) {
this.alertsToLoad = alertsToLoad;
}
@XmlElement(name = "column")
public List<String> getColumns() {
return columns;
}
public void setColumns(List<String> columns) {
this.columns = columns;
}
public int getMergeRepeatInterval() {
return mergeRepeatInterval;
}
public void setMergeRepeatInterval(int mergeRepeatInterval) {
this.mergeRepeatInterval = mergeRepeatInterval;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((activeFilter == null) ? 0 : activeFilter.hashCode());
result = prime * result + alertsToLoad;
result = prime * result + ((columns == null) ? 0 : columns.hashCode());
result = prime * result
+ ((filterMenu == null) ? 0 : filterMenu.hashCode());
result = prime * result + mergeRepeatInterval;
result = prime * result
+ ((openFilter == null) ? 0 : openFilter.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AlertViewPreferences other = (AlertViewPreferences) obj;
if (activeFilter == null) {
if (other.activeFilter != null)
return false;
} else if (!activeFilter.equals(other.activeFilter))
return false;
if (alertsToLoad != other.alertsToLoad)
return false;
if (columns == null) {
if (other.columns != null)
return false;
} else if (!columns.equals(other.columns))
return false;
if (filterMenu == null) {
if (other.filterMenu != null)
return false;
} else if (!filterMenu.equals(other.filterMenu))
return false;
if (mergeRepeatInterval != other.mergeRepeatInterval)
return false;
if (openFilter == null) {
if (other.openFilter != null)
return false;
} else if (!openFilter.equals(other.openFilter))
return false;
return true;
}
public static class FilterMenu {
private String text;
private String filter;
public FilterMenu() {
}
public FilterMenu(String text, String filter) {
this.text = text;
this.filter = filter;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((filter == null) ? 0 : filter.hashCode());
result = prime * result + ((text == null) ? 0 : text.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FilterMenu other = (FilterMenu) obj;
if (filter == null) {
if (other.filter != null)
return false;
} else if (!filter.equals(other.filter))
return false;
if (text == null) {
if (other.text != null)
return false;
} else if (!text.equals(other.text))
return false;
return true;
}
}
public static PreferenceFile<AlertViewPreferences> load(
PreferenceFile.Listener<? super AlertViewPreferences> listener) {
return new PreferenceFile<>("alert_view.xml",
AlertViewPreferences.class, listener);
}
}

View file

@ -0,0 +1,180 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.prefs;
import javax.xml.bind.annotation.XmlRootElement;
import com.raytheon.uf.viz.alertview.Alert.Priority;
import com.raytheon.uf.viz.alertview.ui.popup.AlertPopup;
/**
* Contains the preferences that control how {@link AlertPopup} appears to the
* user.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
@XmlRootElement
public class PopUpPreferences {
public static enum PopUpCorner {
UPPER_LEFT, UPPER_RIGHT, LOWER_LEFT, LOWER_RIGHT;
public String getPrettyName() {
String name = name();
String[] words = name.split("_");
StringBuilder pretty = new StringBuilder(name.length());
for (String word : words) {
if (pretty.length() > 0) {
pretty.append(' ');
}
pretty.append(word.charAt(0));
pretty.append(word.substring(1).toLowerCase());
}
return pretty.toString();
}
public static PopUpCorner fromPrettyName(String corner) {
return valueOf(corner.replace(' ', '_').toUpperCase());
}
}
private String filter;
/* Time in ms. */
private int duration;
private PopUpCorner corner;
private int width;
private int height;
public PopUpPreferences() {
/* Everything needs reasonable defaults to keep PreferenceFile happy. */
filter = Priority.ERROR.name().toLowerCase();
duration = 3000;
corner = PopUpCorner.LOWER_RIGHT;
width = 500;
height = 50;
}
public PopUpPreferences(PopUpPreferences other) {
this.filter = other.getFilter();
this.duration = other.getDuration();
this.corner = other.getCorner();
this.width = other.getWidth();
this.height = other.getHeight();
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
public int getDuration() {
return duration;
}
public void setDuration(int duration) {
this.duration = duration;
}
public PopUpCorner getCorner() {
return corner;
}
public void setCorner(PopUpCorner corner) {
this.corner = corner;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((corner == null) ? 0 : corner.hashCode());
result = prime * result + duration;
result = prime * result + ((filter == null) ? 0 : filter.hashCode());
result = prime * result + height;
result = prime * result + width;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PopUpPreferences other = (PopUpPreferences) obj;
if (corner != other.corner)
return false;
if (duration != other.duration)
return false;
if (filter == null) {
if (other.filter != null)
return false;
} else if (!filter.equals(other.filter))
return false;
if (height != other.height)
return false;
if (width != other.width)
return false;
return true;
}
public static PreferenceFile<PopUpPreferences> load(
PreferenceFile.Listener<? super PopUpPreferences> listener) {
return new PreferenceFile<>("alert_popup.xml", PopUpPreferences.class,
listener);
}
}

View file

@ -0,0 +1,239 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.prefs;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.xml.bind.DataBindingException;
import javax.xml.bind.JAXB;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.viz.alertview.AlertViewPrefStore;
import com.raytheon.uf.viz.alertview.AlertViewPrefStore.AlertViewPrefListener;
/**
*
* Handles the serialization and service management of a preference file. This
* class is designed to be a more friendly way to consume an
* {@link AlertViewPrefStore} service. To load preferences using this class the
* Preference class P should be JAXB serializable and must provide a no-arg
* constructor that initializaes the preferences to a usable state. In cases
* when loading the preferences from files fails the no-arg constructor will be
* used to return a default preference object.
*
* This class listens to changes from the {@link AlertViewPrefStore} service and
* notifies its own listeners of changes to the specified file. It also listens
* to changes to the available AlertViewPrefStore services and when a better
* service becomes available it will reload the preferences from the new service
* and notify listeners. This is especially useful during startup if the
* prefered AlertViewPrefStore starts after other components.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 16, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
* @param <P>
*/
public class PreferenceFile<P> {
private static final String FILTER = "(" + Constants.OBJECTCLASS + "="
+ AlertViewPrefStore.class.getName() + ")";
private Logger logger = LoggerFactory.getLogger(getClass());
private final BundleContext context;
private final String fileName;
private final Class<P> type;
private final Listener<? super P> listener;
private final AlertViewPrefListener prefStoreListener = new AlertViewPrefListener() {
@Override
public void prefFileChanged(String fileName) {
if (fileName.equals(PreferenceFile.this.fileName)) {
updatePreferences(loadFromStore());
}
}
};
private final ServiceListener serviceListener = new ServiceListener() {
@Override
public void serviceChanged(ServiceEvent event) {
@SuppressWarnings("unchecked")
ServiceReference<AlertViewPrefStore> ref = (ServiceReference<AlertViewPrefStore>) event
.getServiceReference();
if (event.getType() == ServiceEvent.REGISTERED) {
add(ref);
} else if (event.getType() == ServiceEvent.UNREGISTERING) {
remove(ref);
}
}
};
private ServiceReference<AlertViewPrefStore> serviceReference;
private AlertViewPrefStore prefStore;
private P preferences;
public PreferenceFile(String fileName, Class<P> type,
Listener<? super P> listener) {
this.fileName = fileName;
this.type = type;
this.listener = listener;
context = FrameworkUtil.getBundle(getClass()).getBundleContext();
try {
context.addServiceListener(serviceListener, FILTER);
} catch (InvalidSyntaxException e) {
/*
* The FILTER is statically defined and very simple syntax so it is
* unlikely that this will ever happen.
*/
throw new RuntimeException(e);
}
this.preferences = updateServiceReference(context
.getServiceReference(AlertViewPrefStore.class));
}
public void close(){
if(serviceReference != null){
prefStore.removeListener(prefStoreListener);
context.ungetService(serviceReference);
}
context.removeServiceListener(serviceListener);
}
protected P updateServiceReference(
ServiceReference<AlertViewPrefStore> serviceReference) {
this.serviceReference = serviceReference;
if (serviceReference != null) {
return updatePrefStore(context.getService(serviceReference));
} else {
return updatePrefStore(null);
}
}
protected P updatePrefStore(AlertViewPrefStore prefStore) {
this.prefStore = prefStore;
if (prefStore != null) {
prefStore.addListener(prefStoreListener);
}
return loadFromStore();
}
protected P loadFromStore() {
P preferences = null;
if (prefStore != null) {
try (InputStream in = prefStore.readConfigFile(fileName)) {
if (in != null) {
preferences = JAXB.unmarshal(in, type);
}
} catch (IOException | DataBindingException e) {
logger.error("Unable to load {} from {}", type.getSimpleName(),
fileName, e);
}
}
if (preferences == null) {
try {
preferences = type.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
/*
* Docs indicate you should have a public no arg constructor, if
* there isn't one then you get RuntimeExceptions.
*/
throw new RuntimeException(e);
}
}
return preferences;
}
protected void updatePreferences(P preferences) {
if (!this.preferences.equals(preferences)) {
this.preferences = preferences;
listener.update(preferences);
}
}
protected void add(ServiceReference<AlertViewPrefStore> ref) {
if (serviceReference == null || ref.compareTo(serviceReference) > 0) {
if (serviceReference != null) {
prefStore.removeListener(prefStoreListener);
context.ungetService(serviceReference);
}
updatePreferences(updateServiceReference(ref));
}
}
protected void remove(ServiceReference<AlertViewPrefStore> ref) {
if (ref.equals(serviceReference)) {
prefStore.removeListener(prefStoreListener);
context.ungetService(serviceReference);
updatePreferences(updateServiceReference(context
.getServiceReference(AlertViewPrefStore.class)));
}
}
public P get() {
return preferences;
}
public void write(P preferences) {
if (prefStore != null) {
try (OutputStream out = prefStore.writeConfigFile(fileName)) {
JAXB.marshal(preferences, out);
} catch (IOException e) {
logger.error("Unable to write {} to {}", type.getSimpleName(),
fileName, e);
}
}
updatePreferences(preferences);
}
public static interface Listener<P> {
public void update(P preference);
}
}

View file

@ -0,0 +1,120 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.prefs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import com.raytheon.uf.viz.alertview.AlertViewPrefStore;
/**
*
* A simple {@link AlertViewPrefStore} that stores preferences in the state area
* that the Eclipse Runtime Platform provides for this bundle. When no user file
* is available the default version of the file is loaded from within this
* bundle.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class RCPPrefStore implements AlertViewPrefStore {
private final Bundle bundle;
private final IPath root = new Path("defaultPrefs");
private final Set<AlertViewPrefListener> listeners = new CopyOnWriteArraySet<>();
public RCPPrefStore() {
this.bundle = FrameworkUtil.getBundle(getClass());
}
@Override
public InputStream readConfigFile(String fileName) throws IOException {
IPath userPath = Platform.getStateLocation(bundle).append(fileName);
File file = userPath.toFile();
if (file.exists()) {
return new FileInputStream(file);
} else {
return FileLocator.openStream(bundle, root.append(fileName), false);
}
}
@Override
public OutputStream writeConfigFile(String fileName)
throws FileNotFoundException {
IPath userPath = Platform.getStateLocation(bundle).append(fileName);
return new NotificationOutputStream(userPath.toFile());
}
@Override
public void addListener(AlertViewPrefListener listener) {
listeners.add(listener);
}
@Override
public void removeListener(AlertViewPrefListener listener) {
listeners.remove(listener);
}
private class NotificationOutputStream extends FileOutputStream {
private final String fileName;
public NotificationOutputStream(File file) throws FileNotFoundException {
super(file);
this.fileName = file.getName();
}
@Override
public void close() throws IOException {
super.close();
for (AlertViewPrefListener listener : listeners) {
listener.prefFileChanged(fileName);
}
}
}
}

View file

@ -0,0 +1,94 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.store;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.AlertDestination;
import com.raytheon.uf.viz.alertview.AlertStore;
import com.raytheon.uf.viz.alertview.prefs.AlertViewPreferences;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
/**
*
* A simple {@link AlertStore} that retains all {@link Alert}s that arrive in
* memory.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class MemoryAlertStore implements AlertStore, AlertDestination,
PreferenceFile.Listener<AlertViewPreferences> {
private ConcurrentLinkedQueue<Alert> alerts = new ConcurrentLinkedQueue<>();
private final PreferenceFile<AlertViewPreferences> prefsFile;
private int retentionCount;
public MemoryAlertStore() {
prefsFile = AlertViewPreferences.load(this);
retentionCount = prefsFile.get().getAlertsToLoad();
}
@Override
public void update(AlertViewPreferences preferences) {
retentionCount = preferences.getAlertsToLoad();
while (alerts.size() > retentionCount) {
alerts.poll();
}
}
/**
* This will get called automatically by declaritive services.
*/
public void deactivate() {
prefsFile.close();
}
@Override
public void handleAlert(Alert alert) {
/* Trim too desired number of alerts */
if (alerts.size() >= retentionCount) {
alerts.poll();
}
alerts.offer(alert);
}
@Override
public List<Alert> getAlerts() {
return Arrays.asList(alerts.toArray(new Alert[0]));
}
}

View file

@ -0,0 +1,174 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.style;
import com.raytheon.uf.viz.alertview.Alert;
/**
*
* Styles that apply to an {@link Alert}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertStyle {
private String filter;
private String backgroundColor;
private String foregroundColor;
private String fontName;
private String fontStyle;
private Integer fontSize;
public AlertStyle() {
}
public AlertStyle(AlertStyle other) {
this.filter = other.filter;
this.backgroundColor = other.backgroundColor;
this.foregroundColor = other.foregroundColor;
}
public String getFilter() {
return filter;
}
public void setFilter(String filter) {
this.filter = filter;
}
public String getBackgroundColor() {
return backgroundColor;
}
public void setBackgroundColor(String backgroundColor) {
this.backgroundColor = backgroundColor;
}
public String getForegroundColor() {
return foregroundColor;
}
public void setForegroundColor(String foregroundColor) {
this.foregroundColor = foregroundColor;
}
public String getFontName() {
return fontName;
}
public void setFontName(String fontName) {
this.fontName = fontName;
}
public String getFontStyle() {
return fontStyle;
}
public void setFontStyle(String fontStyle) {
this.fontStyle = fontStyle;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((backgroundColor == null) ? 0 : backgroundColor.hashCode());
result = prime * result + ((filter == null) ? 0 : filter.hashCode());
result = prime * result
+ ((fontName == null) ? 0 : fontName.hashCode());
result = prime * result
+ ((fontSize == null) ? 0 : fontSize.hashCode());
result = prime * result
+ ((fontStyle == null) ? 0 : fontStyle.hashCode());
result = prime * result
+ ((foregroundColor == null) ? 0 : foregroundColor.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AlertStyle other = (AlertStyle) obj;
if (backgroundColor == null) {
if (other.backgroundColor != null)
return false;
} else if (!backgroundColor.equals(other.backgroundColor))
return false;
if (filter == null) {
if (other.filter != null)
return false;
} else if (!filter.equals(other.filter))
return false;
if (fontName == null) {
if (other.fontName != null)
return false;
} else if (!fontName.equals(other.fontName))
return false;
if (fontSize == null) {
if (other.fontSize != null)
return false;
} else if (!fontSize.equals(other.fontSize))
return false;
if (fontStyle == null) {
if (other.fontStyle != null)
return false;
} else if (!fontStyle.equals(other.fontStyle))
return false;
if (foregroundColor == null) {
if (other.foregroundColor != null)
return false;
} else if (!foregroundColor.equals(other.foregroundColor))
return false;
return true;
}
public Integer getFontSize() {
return fontSize;
}
public void setFontSize(Integer fontSize) {
this.fontSize = fontSize;
}
}

View file

@ -0,0 +1,234 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.style;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.filter.AlertFilter;
import com.raytheon.uf.viz.alertview.filter.FilterManager;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
/**
* Converts {@link AlertStyle}s into SWT colors and fonts.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class StyleManager implements PreferenceFile.Listener<StylePreferences> {
private static final String REGULAR = "Regular";
private static final String BOLD = "Bold";
private static final String ITALIC = "Italic";
private static final String BOLD_ITALIC = BOLD + "-" + ITALIC;
private final FilterManager filterManager = new FilterManager();
private final PreferenceFile<StylePreferences> preferenceFile;
private final CopyOnWriteArraySet<StyleListener> listeners = new CopyOnWriteArraySet<>();
public StyleManager() {
preferenceFile = StylePreferences.load(this);
}
public void addListener(StyleListener listener) {
listeners.add(listener);
}
public void removeListener(StyleListener listener) {
listeners.remove(listener);
}
@Override
public void update(StylePreferences preference) {
for(StyleListener listener : listeners){
listener.updateStyle();
}
}
public void close() {
preferenceFile.close();
}
public Color getForegroundColor(Device device, Alert alert) {
for (AlertStyle style : preferenceFile.get().getStyles()) {
if (style.getForegroundColor() != null) {
AlertFilter filter = filterManager.getFilter(style.getFilter());
if (filter.filter(alert)) {
return parseColor(device, style.getForegroundColor());
}
}
}
return null;
}
public Color getBackgroundColor(Device device, Alert alert) {
for (AlertStyle style : preferenceFile.get().getStyles()) {
if (style.getBackgroundColor() != null) {
AlertFilter filter = filterManager.getFilter(style.getFilter());
if (filter.filter(alert)) {
return parseColor(device, style.getBackgroundColor());
}
}
}
return null;
}
public Font getFont(Device device, Alert alert) {
String name = null;
Integer size = null;
String fstyle = null;
for (AlertStyle style : preferenceFile.get().getStyles()) {
if (name == null && style.getFontName() != null) {
AlertFilter filter = filterManager.getFilter(style.getFilter());
if (filter.filter(alert)) {
name = style.getFontName();
}
}
if (size == null && style.getFontSize() != null) {
AlertFilter filter = filterManager.getFilter(style.getFilter());
if (filter.filter(alert)) {
size = style.getFontSize();
}
}
if (fstyle == null && style.getFontStyle() != null) {
AlertFilter filter = filterManager.getFilter(style.getFilter());
if (filter.filter(alert)) {
fstyle = style.getFontStyle();
}
}
if (name != null && size != null && fstyle != null) {
break;
}
}
return getFont(device, name, size, fstyle);
}
public static Font getFont(Device device, AlertStyle style) {
return getFont(device, style.getFontName(), style.getFontSize(),
style.getFontStyle());
}
public static Font getFont(Device device, String name, Integer size,
String style) {
Integer fstyle = parseFontStyle(style);
if (name != null && size != null && fstyle != null) {
return new Font(device, new FontData(name, size, fstyle));
}
if (name == null && size == null && fstyle == null) {
return device.getSystemFont();
}
FontData systemFontData = device.getSystemFont().getFontData()[0];
if (name == null) {
name = systemFontData.getName();
}
if (size == null) {
size = systemFontData.getHeight();
}
if (fstyle == null) {
fstyle = systemFontData.getStyle();
}
return new Font(device, new FontData(name, size, fstyle));
}
public static void setFont(AlertStyle style, FontData data) {
style.setFontName(data.getName());
style.setFontSize(data.getHeight());
style.setFontStyle(formatFontStyle(data.getStyle()));
}
private static Integer parseFontStyle(String style) {
if (style == null) {
return null;
} else if (style.equalsIgnoreCase(REGULAR)) {
return SWT.NORMAL;
} else if (style.equalsIgnoreCase(BOLD)) {
return SWT.BOLD;
} else if (style.equals(ITALIC)) {
return SWT.ITALIC;
} else if (style.equals(BOLD_ITALIC)) {
return SWT.BOLD | SWT.ITALIC;
}
return null;
}
private static String formatFontStyle(Integer style) {
if (style == null) {
return null;
} else if ((style & SWT.BOLD) == SWT.BOLD
&& (style & SWT.ITALIC) == SWT.ITALIC) {
return BOLD_ITALIC;
} else if ((style & SWT.BOLD) == SWT.BOLD) {
return BOLD;
} else if ((style & SWT.ITALIC) == SWT.ITALIC) {
return ITALIC;
} else if ((style & SWT.NORMAL) == SWT.NORMAL) {
return REGULAR;
}
return null;
}
public static Color parseColor(Device device, String str) {
if (str == null) {
return null;
}
try {
int red = Integer.parseInt(str.substring(1, 3), 16);
int green = Integer.parseInt(str.substring(3, 5), 16);
int blue = Integer.parseInt(str.substring(5, 7), 16);
return new Color(device, red, green, blue);
} catch (NumberFormatException e) {
e.printStackTrace();
}
return null;
}
public static String formatColor(RGB colorValue) {
return String.format("#%02x%02x%02x", colorValue.red, colorValue.green,
colorValue.blue);
}
public static interface StyleListener {
public void updateStyle();
}
}

View file

@ -0,0 +1,117 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.style;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.swt.graphics.RGB;
import com.raytheon.uf.viz.alertview.Alert.Priority;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
/**
*
* JAXB serializable list of {@link AlertStyle}s.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class StylePreferences {
@XmlElement(name = "style")
private List<AlertStyle> styles = new ArrayList<>();
public StylePreferences() {
AlertStyle errorStyle = new AlertStyle();
errorStyle.setFilter(Priority.ERROR.name().toLowerCase());
errorStyle.setForegroundColor(StyleManager.formatColor(new RGB(255, 0,
0)));
styles.add(errorStyle);
}
public StylePreferences(List<AlertStyle> styles) {
this.styles = styles;
}
public List<AlertStyle> getStyles() {
return styles;
}
public void setStyles(List<AlertStyle> styles) {
this.styles = styles;
}
public void addStyle(AlertStyle style) {
if (styles == null) {
styles = new ArrayList<AlertStyle>();
}
styles.add(style);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((styles == null) ? 0 : styles.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StylePreferences other = (StylePreferences) obj;
if (styles == null) {
if (other.styles != null)
return false;
} else if (!styles.equals(other.styles))
return false;
return true;
}
public static PreferenceFile<StylePreferences> load(
PreferenceFile.Listener<? super StylePreferences> listener) {
return new PreferenceFile<>("alert_styles.xml", StylePreferences.class,
listener);
}
}

View file

@ -0,0 +1,276 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.popup;
import java.util.Timer;
import java.util.TimerTask;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.AlertDestination;
import com.raytheon.uf.viz.alertview.filter.FilterManager;
import com.raytheon.uf.viz.alertview.prefs.PopUpPreferences;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
import com.raytheon.uf.viz.alertview.style.StyleManager;
import com.raytheon.uf.viz.alertview.ui.view.AlertView;
import com.raytheon.uf.viz.alertview.ui.view.OpenAlertViewHandler;
/**
*
* An {@link AlertDestination} which displays {@link Alert}s in a small popup
* window. The window only display for a few seconds(exact time is configurable)
* and then disappears. If the user clicks the popup it will open the displayed
* alert in the {@link AlertView}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 17, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertPopup implements AlertDestination,
PreferenceFile.Listener<PopUpPreferences> {
private final PopupAlertTask task = new PopupAlertTask();
private final PreferenceFile<PopUpPreferences> prefsFile;
protected final FilterManager filters = new FilterManager();
protected final StyleManager styles = new StyleManager();
protected PopUpPreferences prefs;
public AlertPopup() {
prefsFile = PopUpPreferences.load(this);
prefs = prefsFile.get();
}
@Override
public void update(PopUpPreferences preferences) {
prefs = preferences;
}
/**
* This will get called automatically by declaritive services.
*/
public void deactivate() {
prefsFile.close();
styles.close();
}
@Override
public void handleAlert(Alert alert) {
if (filters.getFilter(prefs.getFilter()).filter(alert)) {
task.update(alert);
}
}
/**
* This task will run on the UI thread and is responsible for managing the
* popup window. This should not be run directly but will schedule itself
* when {@link #update(Alert)} or {@link #clear(Alert)} is called.
*/
private class PopupAlertTask implements Runnable {
private final Timer timer = new Timer("Remove Alert Popup");
private Shell shell;
private Label label;
/**
* This is the alert that should be dispalyed, the most recent alert
* passed to update which has not been passed to clear.
*/
private volatile Alert alert;
/**
* This is the currently displayed alert, it should only be used from
* the UI thread. If this task is waiting to be run on the UI thread
* then this will not be the same as alert.
*/
private Alert displayedAlert;
/**
* Update the popup window with the provided alert. If the window is not
* currently open then a new popup window will be opened to display the
* alert. If a popup window is already displayed then this alert will
* replace any other alert in the popup window. This method schedules an
* update on the UI thread but it does not block. If multiple calls to
* {@link #update(Alert)} are made before the UI thread becomes
* available then only the most recent Alert will be displayed.
*/
public synchronized void update(Alert alert) {
this.alert = alert;
Display.getDefault().asyncExec(this);
}
/**
* Close the popup if the provided alert is the most recent alert that
* should be displayed. The alert is provided to make clear an atomic
* operation. If another alert has been provided to
* {@link #update(Alert)} since clear was called then it will be a no-op
* because the more recent alert needs to be displayed.
*/
public synchronized void clear(Alert alert) {
if (alert == this.alert) {
this.alert = null;
Display.getDefault().asyncExec(this);
}
}
public void openInAlertView() {
if (displayedAlert != null) {
OpenAlertViewHandler.openInAlertView(displayedAlert);
clear(displayedAlert);
}
}
@Override
public void run() {
this.displayedAlert = this.alert;
if (displayedAlert != null && (shell == null || shell.isDisposed())) {
shell = new Shell(Display.getDefault(), SWT.NO_FOCUS
| SWT.NO_TRIM | SWT.ON_TOP);
GridLayout layout = new GridLayout(1, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
shell.setLayout(layout);
shell.setForeground(Display.getDefault().getSystemColor(
SWT.COLOR_BLACK));
shell.addListener(SWT.Dispose, new Listener() {
@Override
public void handleEvent(Event event) {
shell = null;
}
});
final Composite comp = new Composite(shell, SWT.BORDER);
layout = new GridLayout(1, false);
layout.marginHeight = 0;
layout.marginWidth = 0;
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
comp.setLayout(layout);
comp.setLayoutData(data);
label = new Label(comp, SWT.WRAP);
data = new GridData(SWT.FILL, SWT.FILL, true, true);
label.setLayoutData(data);
label.addMouseListener(new MouseAdapter() {
@Override
public void mouseUp(MouseEvent e) {
openInAlertView();
}
});
shell.setSize(prefs.getWidth(), prefs.getHeight());
Rectangle clientArea = Display.getDefault().getMonitors()[0]
.getClientArea();
int offset = 2;
int startX = offset;
int startY = offset;
switch (prefs.getCorner()) {
case UPPER_LEFT:
startX = clientArea.x + offset;
startY = clientArea.y + offset;
break;
case UPPER_RIGHT:
startX = clientArea.x + clientArea.width
- shell.getSize().x - offset;
startY = clientArea.y + offset;
break;
case LOWER_LEFT:
startX = clientArea.x + offset;
startY = clientArea.y + clientArea.height
- shell.getSize().y - offset;
break;
case LOWER_RIGHT:
startX = clientArea.x + clientArea.width
- shell.getSize().x - offset;
startY = clientArea.y + clientArea.height
- shell.getSize().y - offset;
break;
}
shell.setLocation(startX, startY);
shell.setVisible(true);
}
if (displayedAlert == null) {
if (shell != null && !shell.isDisposed()) {
shell.dispose();
}
} else {
Display display = shell.getDisplay();
label.setBackground(styles.getBackgroundColor(display,
displayedAlert));
label.setForeground(styles.getForegroundColor(display,
displayedAlert));
label.setFont(styles.getFont(display, displayedAlert));
label.setText(displayedAlert.getMessage());
timer.schedule(new ClosePopupTask(displayedAlert),
prefs.getDuration());
}
}
}
/**
* This task is scheduled from the UI thread whenever an alert is displayed
* in a popup. It will call clear after the popup has expired. It is never
* canceled but instead it relies on the atomic nature of
* {@link #clear(Alert)} to ensure that if another alert arrives it will not
* close the popup.
*/
private class ClosePopupTask extends TimerTask {
private final Alert alert;
public ClosePopupTask(Alert alert) {
this.alert = alert;
}
@Override
public void run() {
task.clear(alert);
}
}
}

View file

@ -0,0 +1,213 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.prefs;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import com.raytheon.uf.viz.alertview.prefs.AlertViewPreferences;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
import com.raytheon.uf.viz.alertview.ui.view.AlertTable;
/**
* Preference page for configuring {@link AlertViewPreferences}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 25, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertViewPreferencePage extends PreferencePage implements
PreferenceFile.Listener<AlertViewPreferences> {
protected PreferenceFile<AlertViewPreferences> preferenceFile;
protected PriorityFilterCombo openFilterCombo;
protected Text intervalText;
protected Table columnTable;
@Override
protected Control createContents(Composite parent) {
preferenceFile = AlertViewPreferences.load(this);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(2, false));
new Label(composite, SWT.NONE).setText("Auto Open Priority: ");
openFilterCombo = new PriorityFilterCombo(composite);
new Label(composite, SWT.NONE)
.setText("Hide Duplicate Interval(seconds): ");
intervalText = new Text(composite, SWT.SINGLE | SWT.BORDER);
GridData gridData = new GridData();
gridData.widthHint = 30;
intervalText.setLayoutData(gridData);
Group columnGroup = new Group(composite, SWT.NONE);
columnGroup.setLayout(new GridLayout(2, false));
columnGroup.setText("Column Configuration");
columnTable = new Table(columnGroup, SWT.CHECK);
Composite columnButtonComp = new Composite(columnGroup, SWT.NONE);
RowLayout rowLayout = new RowLayout(SWT.VERTICAL);
rowLayout.fill = true;
rowLayout.justify = true;
columnButtonComp.setLayout(rowLayout);
Button up = new Button(columnButtonComp, SWT.PUSH);
up.setText("Up");
up.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
moveColumn(true);
}
});
Button down = new Button(columnButtonComp, SWT.PUSH);
down.setText("Down");
down.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
moveColumn(false);
}
});
populate();
return composite;
}
public void moveColumn(boolean up) {
int selection = columnTable.getSelectionIndex();
if (selection < 0) {
return;
}
int newIndex;
if (up) {
if (selection == 0) {
return;
}
newIndex = selection - 1;
} else {
if (selection == columnTable.getItemCount() - 1) {
return;
}
newIndex = selection + 2;
}
TableItem oldItem = columnTable.getItem(selection);
TableItem newItem = new TableItem(columnTable, SWT.NONE, newIndex);
newItem.setText(oldItem.getText());
newItem.setChecked(oldItem.getChecked());
oldItem.dispose();
columnTable.setSelection(newItem);
}
protected void populate() {
AlertViewPreferences preferences = preferenceFile.get();
openFilterCombo.setSelection(preferences.getOpenFilter());
intervalText.setText(Double.toString(preferences
.getMergeRepeatInterval() / 1000.0));
columnTable.removeAll();
List<String> columns = preferences.getColumns();
for (String column : columns) {
TableItem item = new TableItem(columnTable, SWT.NONE);
item.setText(column);
item.setChecked(true);
}
for (String column : AlertTable.ALL_COLUMNS) {
if (!columns.contains(column)) {
TableItem item = new TableItem(columnTable, SWT.NONE);
item.setText(column);
item.setChecked(false);
}
}
}
@Override
protected void performDefaults() {
populate();
super.performDefaults();
}
@Override
public boolean performOk() {
AlertViewPreferences newPrefs = new AlertViewPreferences(
preferenceFile.get());
String openFilter = openFilterCombo.getSelection();
if (openFilter != null) {
newPrefs.setOpenFilter(openFilter);
}
newPrefs.setMergeRepeatInterval((int) (Double.parseDouble(intervalText
.getText()) * 1000));
List<String> columns = new ArrayList<>();
for (TableItem item : columnTable.getItems()) {
if (item.getChecked()) {
columns.add(item.getText());
}
}
newPrefs.setColumns(columns);
preferenceFile.write(newPrefs);
return super.performOk();
}
@Override
public void dispose() {
preferenceFile.close();
super.dispose();
}
@Override
public void update(AlertViewPreferences preferences) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (!getControl().isDisposed()) {
populate();
}
}
});
}
}

View file

@ -0,0 +1,60 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.prefs;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.preference.IPreferencePage;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.ui.dialogs.PreferencesUtil;
/**
* Action which opens {@link PreferenceDialog} with the
* {@link AlertViewPreferencePage} and other associated {@link IPreferencePage}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 25, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class OpenPreferencesAction extends Action {
public OpenPreferencesAction() {
super("Preferences");
}
@Override
public void run() {
PreferencesUtil.createPreferenceDialogOn(
null,
AlertViewPreferencePage.class.getName(),
new String[] { AlertViewPreferencePage.class.getName(),
StylePreferencePage.class.getName(),
PopupPreferencePage.class.getName() }, null).open();
}
}

View file

@ -0,0 +1,172 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.prefs;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import com.raytheon.uf.viz.alertview.prefs.PopUpPreferences;
import com.raytheon.uf.viz.alertview.prefs.PopUpPreferences.PopUpCorner;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
/**
* Preference page for configuring {@link PopUpPreferences}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 25, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class PopupPreferencePage extends PreferencePage implements
PreferenceFile.Listener<PopUpPreferences> {
private static final List<String> SIZES = Arrays.asList("Small", "Medium",
"Large");
private static final int BASE_WIDTH = 500;
private static final int BASE_HEIGHT = 50;
protected PreferenceFile<PopUpPreferences> preferenceFile;
protected PriorityFilterCombo filterCombo;
protected Text durationText;
protected Combo positionCombo;
protected Combo sizeCombo;
@Override
protected Control createContents(Composite parent) {
preferenceFile = PopUpPreferences.load(this);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(2, false));
new Label(composite, SWT.NONE).setText("Popup Priority: ");
filterCombo = new PriorityFilterCombo(composite);
new Label(composite, SWT.NONE).setText("Duration(seconds): ");
durationText = new Text(composite, SWT.SINGLE | SWT.BORDER);
GridData gridData = new GridData();
gridData.widthHint = 30;
durationText.setLayoutData(gridData);
new Label(composite, SWT.NONE).setText("Position: ");
positionCombo = new Combo(composite, SWT.READ_ONLY);
for (PopUpCorner position : PopUpCorner.values()) {
positionCombo.add(position.getPrettyName());
}
new Label(composite, SWT.NONE).setText("Size: ");
sizeCombo = new Combo(composite, SWT.READ_ONLY);
for (String size : SIZES) {
sizeCombo.add(size);
}
populate();
return composite;
}
protected void populate() {
PopUpPreferences preferences = preferenceFile.get();
filterCombo.setSelection(preferences.getFilter());
durationText
.setText(Double.toString(preferences.getDuration() / 1000.0));
positionCombo.select(positionCombo.indexOf(preferences.getCorner()
.getPrettyName()));
boolean sizeFound = false;
for (int i = 0; i < SIZES.size(); i += 1) {
if (preferences.getHeight() == BASE_HEIGHT + 25 * i
&& preferences.getWidth() == BASE_WIDTH + 50 * i) {
sizeCombo.select(i);
sizeFound = true;
break;
}
}
if (!sizeFound) {
if (sizeCombo.getItemCount() > SIZES.size()) {
sizeCombo.remove(SIZES.size());
}
sizeCombo.add(preferences.getWidth() + " x "
+ preferences.getHeight());
sizeCombo.select(SIZES.size());
}
}
@Override
protected void performDefaults() {
populate();
super.performDefaults();
}
@Override
public boolean performOk() {
PopUpPreferences newPrefs = new PopUpPreferences(preferenceFile.get());
String filter = filterCombo.getSelection();
if (filter != null) {
newPrefs.setFilter(filter);
}
newPrefs.setDuration((int) (Double.parseDouble(durationText.getText()) * 1000));
newPrefs.setCorner(PopUpCorner.fromPrettyName(positionCombo.getText()));
int index = SIZES.indexOf(sizeCombo.getText());
if (index >= 0) {
newPrefs.setWidth(BASE_WIDTH + 50 * index);
newPrefs.setHeight(BASE_HEIGHT + 25 * index);
}
preferenceFile.write(newPrefs);
return super.performOk();
}
@Override
public void dispose() {
preferenceFile.close();
super.dispose();
}
@Override
public void update(PopUpPreferences preferences) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (!getControl().isDisposed()) {
populate();
}
}
});
}
}

View file

@ -0,0 +1,96 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.prefs;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import com.raytheon.uf.viz.alertview.Alert.Priority;
import com.raytheon.uf.viz.alertview.filter.FilterManager;
/**
* Class for using an {@link Combo} to select a priority level.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 25, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class PriorityFilterCombo {
/**
* Mapping for pretty user text to filter names for populating priority
* combos.
*/
private static final Map<String, String> MAPPING = getPriorityFilterMapping();
private final Combo combo;
public PriorityFilterCombo(Composite parent) {
combo = new Combo(parent, SWT.READ_ONLY);
for (Entry<String, String> entry : MAPPING.entrySet()) {
combo.add(entry.getKey());
}
}
public void setSelection(String filter) {
for (Entry<String, String> entry : MAPPING.entrySet()) {
if (filter.equals(entry.getValue())) {
int index = combo.indexOf(entry.getKey());
if (index >= 0) {
combo.select(index);
} else {
combo.deselectAll();
}
}
}
}
public String getSelection() {
String filter = combo.getText();
if (filter != null && !filter.isEmpty()) {
return MAPPING.get(filter);
}
return null;
}
private static Map<String, String> getPriorityFilterMapping() {
Map<String, String> mapping = new LinkedHashMap<>();
mapping.put("None", FilterManager.NONE);
mapping.put("Error", Priority.ERROR.name().toLowerCase());
mapping.put("Error+Warning", FilterManager.WARN_PLUS);
mapping.put("Error+Warning+Info", FilterManager.INFO_PLUS);
mapping.put("All", FilterManager.ALL);
return mapping;
}
}

View file

@ -0,0 +1,306 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.prefs;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.preference.ColorSelector;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FontDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import com.raytheon.uf.viz.alertview.Alert.Priority;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
import com.raytheon.uf.viz.alertview.style.AlertStyle;
import com.raytheon.uf.viz.alertview.style.StyleManager;
import com.raytheon.uf.viz.alertview.style.StylePreferences;
/**
* Preference page for configuring {@link StylePreferences}
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 25, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class StylePreferencePage extends PreferencePage implements
PreferenceFile.Listener<StylePreferences> {
protected PreferenceFile<StylePreferences> preferenceFile;
protected Table table;
protected Combo filterCombo;
protected ColorSelector foregroundSelector;
protected ColorSelector backgroundSelector;
protected Button fontButton;
@Override
protected Control createContents(Composite parent) {
preferenceFile = StylePreferences.load(this);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(new GridLayout(1, false));
Composite tableComp = new Composite(composite, SWT.NONE);
tableComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
tableComp.setLayout(new GridLayout(2, false));
table = new Table(tableComp, SWT.NONE);
table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
table.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
styleSelected();
}
});
Composite columnButtonComp = new Composite(tableComp, SWT.NONE);
RowLayout rowLayout = new RowLayout(SWT.VERTICAL);
rowLayout.fill = true;
rowLayout.justify = true;
columnButtonComp.setLayout(rowLayout);
columnButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false,
true));
Button newButton = new Button(columnButtonComp, SWT.PUSH);
newButton.setText("New");
newButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
newStyle();
}
});
Button deleteButton = new Button(columnButtonComp, SWT.PUSH);
deleteButton.setText("Delete");
deleteButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
deleteStyle();
}
});
Composite editComp = new Composite(composite, SWT.NONE);
editComp.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false,
false));
editComp.setLayout(new GridLayout(2, false));
new Label(editComp, SWT.NONE).setText("Priority: ");
filterCombo = new Combo(editComp, SWT.READ_ONLY);
for (Priority priority : Priority.values()) {
filterCombo.add(priority.name());
}
filterCombo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
filterSelected();
}
});
new Label(editComp, SWT.NONE).setText("Foreground Color: ");
foregroundSelector = new ColorSelector(editComp);
foregroundSelector.getButton().setLayoutData(
new GridData(GridData.FILL_HORIZONTAL));
foregroundSelector.addListener(new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
foregroundSelected();
}
});
new Label(editComp, SWT.NONE).setText("Background Color: ");
backgroundSelector = new ColorSelector(editComp);
backgroundSelector.getButton().setLayoutData(
new GridData(GridData.FILL_HORIZONTAL));
backgroundSelector.addListener(new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
backgroundSelected();
}
});
new Label(editComp, SWT.NONE).setText("Font: ");
fontButton = new Button(editComp, SWT.PUSH);
fontButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fontButton.setText("Configure Font");
fontButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fontSelected();
}
});
performDefaults();
styleSelected();
return composite;
}
protected void fontSelected() {
FontData data = new FontDialog(getShell()).open();
if (data == null) {
return;
}
TableItem selection = table.getSelection()[0];
AlertStyle style = (AlertStyle) selection.getData();
StyleManager.setFont(style, data);
selection.setFont(StyleManager.getFont(getShell().getDisplay(), style));
}
protected void backgroundSelected() {
TableItem selection = table.getSelection()[0];
selection.setBackground(new Color(getShell().getDisplay(),
backgroundSelector.getColorValue()));
AlertStyle style = (AlertStyle) selection.getData();
style.setBackgroundColor(StyleManager.formatColor(backgroundSelector
.getColorValue()));
}
protected void foregroundSelected() {
TableItem selection = table.getSelection()[0];
selection.setForeground(new Color(getShell().getDisplay(),
foregroundSelector.getColorValue()));
AlertStyle style = (AlertStyle) selection.getData();
style.setForegroundColor(StyleManager.formatColor(foregroundSelector
.getColorValue()));
}
protected void filterSelected() {
TableItem selection = table.getSelection()[0];
selection.setText(filterCombo.getItem(filterCombo.getSelectionIndex()));
AlertStyle style = (AlertStyle) selection.getData();
style.setFilter(selection.getText().toLowerCase());
}
protected void newStyle() {
TableItem item = new TableItem(table, SWT.NONE);
item.setText("INFO");
AlertStyle style = new AlertStyle();
style.setFilter(item.getText().toLowerCase());
item.setData(style);
table.select(table.indexOf(item));
styleSelected();
}
@Override
public void dispose() {
preferenceFile.close();
super.dispose();
}
protected void deleteStyle() {
table.getSelection()[0].dispose();
styleSelected();
}
protected void styleSelected() {
int index = table.getSelectionIndex();
if (index < 0) {
filterCombo.deselectAll();
filterCombo.setEnabled(false);
foregroundSelector.setEnabled(false);
backgroundSelector.setEnabled(false);
fontButton.setEnabled(false);
return;
}
TableItem selection = table.getItem(index);
filterCombo.setEnabled(true);
foregroundSelector.setEnabled(true);
backgroundSelector.setEnabled(true);
fontButton.setEnabled(true);
index = filterCombo.indexOf(selection.getText());
filterCombo.select(index);
backgroundSelector.setColorValue(selection.getBackground().getRGB());
foregroundSelector.setColorValue(selection.getForeground().getRGB());
}
@Override
protected void performDefaults() {
table.removeAll();
for (AlertStyle style : preferenceFile.get().getStyles()) {
TableItem item = new TableItem(table, SWT.NONE);
item.setText(style.getFilter().toUpperCase());
item.setBackground(StyleManager.parseColor(getShell().getDisplay(),
style.getBackgroundColor()));
item.setForeground(StyleManager.parseColor(getShell().getDisplay(),
style.getForegroundColor()));
item.setFont(StyleManager.getFont(getShell().getDisplay(), style));
item.setData(new AlertStyle(style));
}
super.performDefaults();
}
@Override
public boolean performOk() {
List<AlertStyle> styles = new ArrayList<AlertStyle>();
for (TableItem item : table.getItems()) {
styles.add((AlertStyle) item.getData());
}
StylePreferences newPrefs = new StylePreferences();
newPrefs.setStyles(styles);
preferenceFile.write(newPrefs);
return super.performOk();
}
@Override
public void update(StylePreferences preferences) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
if (!getControl().isDisposed()) {
performDefaults();
}
}
});
}
}

View file

@ -0,0 +1,160 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.view;
import java.io.IOException;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IHyperlink;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.console.TextConsoleViewer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.action.SaveToFileAction;
/**
*
* Used for viewing the details of {@link Alert}s. Since most alerts are
* generated from logged errors this console is created so that links appear in
* stack traces when the view is used in eclipse.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertConsoleViewer extends TextConsoleViewer {
private static Logger logger = LoggerFactory.getLogger(AlertView.class);
private AlertConsole console;
private Alert alert;
public AlertConsoleViewer(Composite parent) {
this(parent, new AlertConsole());
}
private AlertConsoleViewer(Composite parent, AlertConsole console) {
super(parent, console);
this.console = console;
console.setViewer(this);
initialize();
}
private void initialize() {
StyledText text = getTextWidget();
text.setEditable(false);
Menu menu = new Menu(text);
text.setMenu(menu);
menu.addMenuListener(new MenuAdapter() {
@Override
public void menuShown(MenuEvent e) {
populateContextMenu(getTextWidget().getMenu());
}
});
}
protected void populateContextMenu(Menu menu) {
for (MenuItem item : menu.getItems()) {
item.dispose();
}
if (alert == null) {
return;
}
new ActionContributionItem(new SaveToFileAction(alert)).fill(menu, -1);
}
public void setAlert(Alert alert) {
if (this.alert == alert) {
return;
}
this.alert = alert;
console.clearConsole();
if (alert == null) {
return;
}
String details = alert.getDetails();
if (details.isEmpty()) {
details = alert.getMessage();
}
try (IOConsoleOutputStream os = console.newOutputStream()) {
os.write(details);
} catch (IOException e) {
logger.error("Unexpected IO exception writing to console.", e);
}
}
protected void redraw() {
Display.getDefault().syncExec(new Runnable() {
@Override
public void run() {
getTextWidget().redraw();
}
});
}
private static class AlertConsole extends IOConsole {
private AlertConsoleViewer viewer;
public AlertConsole() {
super("AlertViewConsole", "javaStackTraceConsole", null);
ConsolePlugin.getDefault().getConsoleManager()
.createPatternMatchListeners(this);
}
public void setViewer(AlertConsoleViewer viewer) {
this.viewer = viewer;
}
@Override
public void addHyperlink(IHyperlink hyperlink, int offset, int length)
throws BadLocationException {
super.addHyperlink(hyperlink, offset, length);
viewer.redraw();
}
}
}

View file

@ -0,0 +1,456 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.view;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.progress.UIJob;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.action.SaveToFileAction;
import com.raytheon.uf.viz.alertview.filter.AlertFilter;
import com.raytheon.uf.viz.alertview.style.StyleManager;
import com.raytheon.uf.viz.alertview.style.StyleManager.StyleListener;
/**
*
* Table that displays {@link Alert}s.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
* Jun 23, 2015 4474 njensen Added removeAll() and getFilter()
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertTable extends Composite implements StyleListener {
public static final String COLUMN_TIME = "Time";
public static final String COLUMN_PRIORITY = "Priority";
public static final String COLUMN_ORIGIN = "Origin";
public static final String COLUMN_MESSAGE = "Message";
public static final String[] ALL_COLUMNS = { COLUMN_TIME, COLUMN_PRIORITY,
COLUMN_ORIGIN, COLUMN_MESSAGE };
private StyleManager styles = new StyleManager();
private BlockingQueue<Alert> alertsToAdd = new LinkedBlockingQueue<Alert>();
private Table alertTable;
private AlertFilter filter;
private int mergeRepeatInterval;
/**
* When things are going terribly wrong and a gazillion alerts are coming in
* the UI will freeze if they aren't throttled a bit. This job tries to be
* reasonablish about how much CPU to suck updating the table.
*/
private Job addAlertJob = new UIJob("Updating AlertView") {
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (AlertTable.this.isDisposed()) {
alertsToAdd.clear();
return Status.OK_STATUS;
}
Alert next = alertsToAdd.poll();
if (next != null) {
int processed = 0;
while (next != null) {
addAlertInternal(next);
if (processed++ > 500) {
this.schedule(100);
break;
}
next = alertsToAdd.poll();
}
packColumns();
}
return Status.OK_STATUS;
}
};
public AlertTable(Composite parent, List<String> columns) {
super(parent, SWT.NONE);
this.setLayout(new FillLayout());
createAlertTable();
rebuildColums(columns);
styles.addListener(this);
}
protected void createAlertTable() {
alertTable = new Table(this, SWT.H_SCROLL | SWT.V_SCROLL
| SWT.FULL_SELECTION | SWT.MULTI);
alertTable.setHeaderVisible(true);
alertTable.setLinesVisible(true);
alertTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
alertSelected();
}
});
alertTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
alertDoubleClick();
}
});
alertTable.addMouseMoveListener(new MouseMoveListener() {
@Override
public void mouseMove(MouseEvent e) {
alertTable.setToolTipText(null);
}
});
alertTable.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseHover(MouseEvent e) {
TableItem item = alertTable.getItem(new Point(e.x, e.y));
if (item == null) {
alertTable.setToolTipText(null);
} else {
Alert alert = getAlert(item);
alertTable.setToolTipText(getToolTip(alert));
}
}
});
Menu menu = new Menu(alertTable);
alertTable.setMenu(menu);
menu.addMenuListener(new MenuAdapter() {
@Override
public void menuShown(MenuEvent e) {
populateContextMenu(alertTable.getMenu());
}
});
}
public void addAlert(Alert alert) {
alertsToAdd.add(alert);
addAlertJob.schedule();
}
protected TableItem addAlertInternal(Alert alert) {
if (filter != null && !filter.filter(alert)) {
return null;
}
TableItem newItem = null;
for (int index = 0; index < alertTable.getItemCount(); index += 1) {
TableItem item = alertTable.getItem(index);
List<Alert> alerts = getAlerts(item);
Alert sample = alerts.get(0);
if (alerts.contains(alert)) {
return item;
} else if (equalsEnough(sample, alert)) {
alerts.add(alert);
return item;
} else if (sample.getTime().before(alert.getTime())) {
newItem = new TableItem(alertTable, SWT.NONE, index);
break;
}
}
if (newItem == null) {
newItem = new TableItem(alertTable, SWT.NONE);
}
newItem.setData(new ArrayList<Alert>(Arrays.asList(alert)));
newItem.setText(getText(alert));
applyStyle(newItem);
alertTable.showItem(newItem);
return newItem;
}
/**
* Used to determine if 2 messages are similar enough that they should not
* be displayed as separate items.
*/
protected boolean equalsEnough(Alert a1, Alert a2) {
if (a1.getMessage() == null) {
if (a2.getMessage() != null) {
return false;
}
} else if (!a1.getMessage().equals(a2.getMessage())) {
return false;
}
if (a1.getOrigin() == null) {
if (a2.getOrigin() != null) {
return false;
}
} else if (!a1.getOrigin().equals(a2.getOrigin())) {
return false;
}
if (a1.getDetails() == null) {
if (a2.getDetails() != null) {
return false;
}
} else if (!a1.getDetails().equals(a2.getDetails())) {
return false;
}
long timeDiff = Math.abs(a2.getTime().getTime()
- a1.getTime().getTime());
if (timeDiff > mergeRepeatInterval) {
return false;
} else {
return true;
}
}
public void setMergeRepeatInterval(int mergeRepeatInterval) {
this.mergeRepeatInterval = mergeRepeatInterval;
}
protected void applyStyle(TableItem item) {
Alert alert = getAlert(item);
item.setBackground(styles.getBackgroundColor(item.getDisplay(), alert));
item.setForeground(styles.getForegroundColor(item.getDisplay(), alert));
item.setFont(styles.getFont(item.getDisplay(), alert));
}
public void setFilter(AlertFilter filter) {
this.filter = filter;
for (TableItem item : alertTable.getSelection()) {
Alert alert = getAlert(item);
if (!filter.filter(alert)) {
item.dispose();
}
}
for (TableItem item : alertTable.getItems()) {
Alert alert = getAlert(item);
if (!filter.filter(alert)) {
item.dispose();
}
}
}
protected AlertFilter getFilter() {
return this.filter;
}
public void select(Alert alert) {
if (alertsToAdd.contains(alert)) {
TableItem item = addAlertInternal(alert);
alertTable.setSelection(alertTable.indexOf(item));
alertSelected();
return;
}
for (TableItem item : alertTable.getItems()) {
List<Alert> alerts = getAlerts(item);
if (alerts.contains(alert)) {
alertTable.setSelection(alertTable.indexOf(item));
alertSelected();
return;
}
}
}
public void packColumns() {
for (TableColumn column : alertTable.getColumns()) {
column.pack();
}
}
protected String[] getText(Alert alert) {
TableColumn[] columns = alertTable.getColumns();
String[] text = new String[columns.length];
for (int i = 0; i < columns.length; i += 1) {
if (columns[i].getText().equals(COLUMN_MESSAGE)) {
text[i] = alert.getMessage().split("\n")[0];
} else if (columns[i].getText().equals(COLUMN_TIME)) {
text[i] = new SimpleDateFormat("hh:mm a").format(alert
.getTime());
} else if (columns[i].getText().equals(COLUMN_PRIORITY)) {
text[i] = alert.getPriority().toString();
} else if (columns[i].getText().equals(COLUMN_ORIGIN)) {
text[i] = alert.getOrigin();
} else {
text[i] = "Unknown Field";
}
}
return text;
}
public void rebuildColums(List<String> columns) {
for (TableColumn column : alertTable.getColumns()) {
column.dispose();
}
for (String columnText : columns) {
TableColumn column = new TableColumn(alertTable, SWT.NONE);
column.setText(columnText);
}
for (TableItem item : alertTable.getItems()) {
item.setText(getText(getAlert(item)));
}
for (TableColumn column : alertTable.getColumns()) {
column.pack();
}
}
protected String getToolTip(Alert alert) {
StringBuilder toolTip = new StringBuilder();
if (alert.getTime() != null) {
SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd_HH:mm:ss.SSS");
toolTip.append("Time: ").append(sdf.format(alert.getTime()))
.append("\n");
}
if (alert.getPriority() != null) {
toolTip.append("Priority: ").append(alert.getPriority())
.append("\n");
}
if (toolTip.charAt(toolTip.length() - 1) == '\n') {
toolTip.deleteCharAt(toolTip.length() - 1);
}
return toolTip.toString();
}
protected void populateContextMenu(Menu menu) {
for (MenuItem item : menu.getItems()) {
item.dispose();
}
Alert alert = getSingleSelection();
if (alert != null) {
new ActionContributionItem(new SaveToFileAction(alert)).fill(menu,
-1);
}
}
public Alert getSingleSelection() {
TableItem[] selection = alertTable.getSelection();
if (selection == null || selection.length != 1) {
return null;
} else {
return getAlert(selection[0]);
}
}
public List<Alert> getMultiSelection() {
TableItem[] selection = alertTable.getSelection();
if (selection == null || selection.length == 0) {
return Collections.emptyList();
}
List<Alert> result = new ArrayList<Alert>();
for (int i = 0; i < selection.length; i += 1) {
result.addAll(getAlerts(selection[i]));
}
return result;
}
public Alert getAlert(TableItem item) {
return getAlerts(item).get(0);
}
@SuppressWarnings("unchecked")
public List<Alert> getAlerts(TableItem item) {
return (List<Alert>) item.getData();
}
public void removeAll() {
alertTable.removeAll();
}
@Override
public void dispose() {
super.dispose();
styles.close();
}
protected void alertSelected() {
// sub classes can override this easily
}
protected void alertDoubleClick() {
// sub classes can override this easily
}
@Override
public void updateStyle() {
Display display = getDisplay();
if (display.isDisposed()) {
return;
}
display.asyncExec(new Runnable() {
@Override
public void run() {
if (alertTable.isDisposed()) {
return;
}
for (TableItem item : alertTable.getItems()) {
applyStyle(item);
}
}
});
}
}

View file

@ -0,0 +1,245 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.view;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.AlertDestination;
import com.raytheon.uf.viz.alertview.AlertStore;
import com.raytheon.uf.viz.alertview.filter.AlertFilter;
import com.raytheon.uf.viz.alertview.filter.FilterManager;
import com.raytheon.uf.viz.alertview.prefs.AlertViewPreferences;
import com.raytheon.uf.viz.alertview.prefs.AlertViewPreferences.FilterMenu;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
import com.raytheon.uf.viz.alertview.ui.prefs.OpenPreferencesAction;
/**
*
* {@link IViewPart} for displaying {@link Alert}s. View is essentially just a
* combination of an {@link AlertTable} and an {@link AlertConsoleViewer}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
* Jun 22, 2015 4474 njensen Fix bugs
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertView extends ViewPart implements AlertDestination,
PreferenceFile.Listener<AlertViewPreferences> {
private static Logger logger = LoggerFactory.getLogger(AlertView.class);
private FilterManager filterManager = new FilterManager();
private ServiceRegistration<AlertDestination> destinationRegistration;
private PreferenceFile<AlertViewPreferences> preferencesFile;
private SashForm sashForm;
private AlertTable alertTable;
private AlertConsoleViewer detailsConsoleViewer;
@Override
public void createPartControl(Composite parent) {
preferencesFile = AlertViewPreferences.load(this);
AlertViewPreferences preferences = preferencesFile.get();
sashForm = new SashForm(parent, SWT.NONE);
sashForm.setOrientation(SWT.VERTICAL);
alertTable = new AlertTable(sashForm, preferences.getColumns()) {
@Override
protected void alertSelected() {
detailsConsoleViewer.setAlert(alertTable.getSingleSelection());
}
@Override
protected void alertDoubleClick() {
if (sashForm.getMaximizedControl() == alertTable) {
sashForm.setMaximizedControl(null);
} else {
sashForm.setMaximizedControl(alertTable);
}
}
};
detailsConsoleViewer = new AlertConsoleViewer(sashForm);
sashForm.setMaximizedControl(alertTable);
alertTable.setMergeRepeatInterval(preferences.getMergeRepeatInterval());
populateFilterMenu();
destinationRegistration = getBundleContext().registerService(
AlertDestination.class, this, null);
}
protected void populateFilterMenu() {
/*
* TODO the menu button creates excessive unusable space in CAVE because
* there are no toolbar items and the tabs are so small.
*/
IMenuManager menuManager = getViewSite().getActionBars()
.getMenuManager();
menuManager.removeAll();
MenuManager filterMenu = new MenuManager("Show", null);
menuManager.add(filterMenu);
AlertViewPreferences prefs = preferencesFile.get();
for (FilterMenu menuItem : prefs.getFilterMenu()) {
Action action = new ShowFilteredAction(menuItem);
if (prefs.getActiveFilter().equals(menuItem.getFilter())) {
action.setChecked(true);
action.run();
}
filterMenu.add(action);
}
menuManager.add(new OpenPreferencesAction());
}
private void loadAlerts() {
BundleContext context = getBundleContext();
ServiceReference<AlertStore> ref = context
.getServiceReference(AlertStore.class);
if (ref != null) {
AlertStore store = context.getService(ref);
for (Alert alert : store.getAlerts()) {
alertTable.addAlert(alert);
}
context.ungetService(ref);
}
alertTable.packColumns();
}
@Override
public void setFocus() {
alertTable.setFocus();
}
@Override
public void dispose() {
destinationRegistration.unregister();
preferencesFile.close();
super.dispose();
}
@Override
public void handleAlert(Alert alert) {
alertTable.addAlert(alert);
}
@Override
public void update(final AlertViewPreferences preferences) {
Display display = Display.getCurrent();
if (display.isDisposed()) {
return;
}
display.asyncExec(new Runnable() {
@Override
public void run() {
if (alertTable.isDisposed()) {
return;
}
alertTable.setMergeRepeatInterval(preferences
.getMergeRepeatInterval());
alertTable.rebuildColums(preferences.getColumns());
populateFilterMenu();
}
});
}
public static void show(IWorkbenchWindow window, Alert alert) {
IWorkbenchPage activePage = window.getActivePage();
try {
AlertView view = (AlertView) activePage.showView(AlertView.class
.getName());
if (alert != null) {
view.handleAlert(alert);
view.alertTable.select(alert);
view.sashForm.setMaximizedControl(null);
}
} catch (PartInitException e) {
logger.error("Cannot open AlertView", e);
}
}
protected static BundleContext getBundleContext() {
return FrameworkUtil.getBundle(AlertView.class).getBundleContext();
}
private class ShowFilteredAction extends Action {
private final String filterName;
private final AlertFilter filter;
public ShowFilteredAction(FilterMenu menuItem) {
super(menuItem.getText(), IAction.AS_RADIO_BUTTON);
this.filterName = menuItem.getFilter();
this.filter = filterManager.getFilter(filterName);
}
@Override
public void run() {
if (!this.filter.equals(alertTable.getFilter())) {
alertTable.setFilter(filter);
detailsConsoleViewer.setAlert(alertTable.getSingleSelection());
loadAlerts();
AlertViewPreferences prefs = preferencesFile.get();
if (!filterName.equals(prefs.getActiveFilter())) {
prefs = new AlertViewPreferences(prefs);
prefs.setActiveFilter(filterName);
preferencesFile.write(prefs);
}
}
}
}
}

View file

@ -0,0 +1,81 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.view;
import org.eclipse.swt.widgets.Display;
import com.raytheon.uf.viz.alertview.Alert;
import com.raytheon.uf.viz.alertview.AlertDestination;
import com.raytheon.uf.viz.alertview.filter.AlertFilter;
import com.raytheon.uf.viz.alertview.filter.FilterManager;
import com.raytheon.uf.viz.alertview.prefs.AlertViewPreferences;
import com.raytheon.uf.viz.alertview.prefs.PreferenceFile;
/**
* Automatically open {@link AlertView} whenever new {@link Alert}s arrive that
* have a high enough priority.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 25, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class AlertViewAutoOpen implements AlertDestination,
PreferenceFile.Listener<AlertViewPreferences> {
private final PreferenceFile<AlertViewPreferences> prefsFile;
private final FilterManager filters = new FilterManager();
private AlertFilter filter;
public AlertViewAutoOpen() {
prefsFile = AlertViewPreferences.load(this);
filter = filters.getFilter(prefsFile.get().getOpenFilter());
}
@Override
public void update(AlertViewPreferences preference) {
filter = filters.getFilter(prefsFile.get().getOpenFilter());
}
@Override
public void handleAlert(final Alert alert) {
if (filter.filter(alert)) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
OpenAlertViewHandler.openInAlertView(alert);
}
});
}
}
}

View file

@ -0,0 +1,113 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.alertview.ui.view;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import com.raytheon.uf.viz.alertview.Alert;
/**
*
* {@link IHandler} that opens an {@link AlertView}.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- --------- --------------------------
* Jun 18, 2015 4474 bsteffen Initial creation
*
* </pre>
*
* @author bsteffen
* @version 1.0
*/
public class OpenAlertViewHandler extends AbstractHandler {
private final Alert alert;
public OpenAlertViewHandler() {
this.alert = null;
}
public OpenAlertViewHandler(Alert alert) {
this.alert = alert;
}
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
openInAlertView(alert);
return null;
}
public static void openInAlertView(Alert alert) {
IWorkbench workbench = PlatformUI.getWorkbench();
IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
if (workbench.isStarting()) {
workbench.addWindowListener(new ShowAlertViewWindowListener(alert));
} else if (window != null) {
AlertView.show(window, alert);
}
}
/**
* If the user clicks on the alert popup while the workbench is starting
* then this listener will be used to wait until the workbench window is
* opened and then display the alert.
*/
private static class ShowAlertViewWindowListener implements IWindowListener {
private final Alert alert;
public ShowAlertViewWindowListener(Alert alert) {
this.alert = alert;
}
@Override
public void windowOpened(IWorkbenchWindow window) {
AlertView.show(window, alert);
window.getWorkbench().removeWindowListener(this);
}
@Override
public void windowDeactivated(IWorkbenchWindow window) {
/* Unused method required by interface. */
}
@Override
public void windowClosed(IWorkbenchWindow window) {
/* Unused method required by interface. */
}
@Override
public void windowActivated(IWorkbenchWindow window) {
/* Unused method required by interface. */
}
}
}

View file

@ -33,6 +33,8 @@ import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
@ -68,6 +70,7 @@ import com.raytheon.uf.viz.alertviz.config.AlertMetadata;
* 13 Jan 2011 7375 cjeanbap Commented out shell.setVisible(...) in
* acknowledgeLastMessage().
* 20 Apr 2015 4311 lvenable Fixed text field to accept really long text strings.
* 29 Jun 2015 4311 randerso Reworking AlertViz dialogs to be resizable.
*
* </pre>
*
@ -77,6 +80,20 @@ import com.raytheon.uf.viz.alertviz.config.AlertMetadata;
*/
public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
MouseListener {
private static final int MAX_INITIAL_LINES = 5;
private static final int WIDTH_IN_CHARS = 135;
private static final double PERCENT_OF_SCREEN_WIDTH = 0.75;
private static final int NUM_LIST_ITEMS = 10;
/*
* Adjustment for SWT bug where shell.getSize() returns incorrect value when
* SWT.ON_TOP style is used.
*/
private static final int SWT_BUG_FACTOR = 6;
/**
* Dialog shell.
*/
@ -87,21 +104,11 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
*/
private Display display;
/**
* Font used for the controls.
*/
private Font controlFont;
/**
* Font used for labels
*/
private Font labelFont;
/**
* Font used for the double click label.
*/
private Font dblClickLblFont;
/**
* Message text field.
*/
@ -268,7 +275,9 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
*/
private boolean initialized = false;
private final AlertVisualization av;
private boolean first;
private int controlWidth;
/**
* Constructor.
@ -285,13 +294,12 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
* Color to be displayed at startup.
*/
public AlertPopupMessageDlg(Shell parent, StatusMessage statMsg,
boolean expanded, Listener listener, RGB startUpRGB,
AlertVisualization av) {
boolean expanded, Listener listener, RGB startUpRGB) {
super(parent, 0);
hideListener = listener;
statMsgArray.add(statMsg);
this.expanded = expanded;
this.av = av;
this.first = true;
initShell(startUpRGB);
}
@ -303,15 +311,14 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
Shell parent = getParent();
display = parent.getDisplay();
shell = new Shell(parent, SWT.ON_TOP);
shell = new Shell(parent, SWT.ON_TOP | SWT.RESIZE);
shell.setText("Alert Visualization Popup Message Dialog");
Rectangle prvLocation = av.getAlertPopupMsgPrvLocation();
if (prvLocation != null) {
shell.getBounds().add(prvLocation);
}
// Create the main layout for the shell.
GridLayout mainLayout = new GridLayout(1, false);
mainLayout.marginWidth = 0;
mainLayout.marginHeight = 0;
mainLayout.verticalSpacing = 0;
shell.setLayout(mainLayout);
// initialize data, fonts, and arrays
@ -345,12 +352,13 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
* @return True/False/null.
*/
public Object open() {
shell.pack();
setInitialDialogLocation();
initialized = true;
showHideLog();
shell.open();
while (!shell.isDisposed()) {
@ -361,9 +369,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
initialized = false;
controlFont.dispose();
labelFont.dispose();
dblClickLblFont.dispose();
return null;
}
@ -372,10 +378,26 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
* Initialize font data
*/
private void initalizeData() {
controlFont = new Font(shell.getDisplay(), "Monospace", 10, SWT.NORMAL);
labelFont = new Font(shell.getDisplay(), "Monospace", 14, SWT.BOLD);
dblClickLblFont = new Font(shell.getDisplay(), "Monospace", 10,
SWT.BOLD);
FontData fontData = display.getSystemFont().getFontData()[0];
labelFont = new Font(shell.getDisplay(), fontData.getName(),
(int) (fontData.getHeight() * 1.4), SWT.BOLD);
/*
* compute preferred height to display entire message.
*/
int screenWidth = display.getPrimaryMonitor().getBounds().width;
/*
* compute width of controls as the lesser of WIDTH_IN_CHARS or
* PERCENT_OF_SCREEN_WIDTH
*/
GC gc = new GC(display);
gc.setFont(display.getSystemFont());
int charWidth = gc.getFontMetrics().getAverageCharWidth();
gc.dispose();
controlWidth = Math.min(charWidth * WIDTH_IN_CHARS,
(int) (screenWidth * PERCENT_OF_SCREEN_WIDTH));
}
/**
@ -399,7 +421,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
private void createTitleBarLabel() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
gd.horizontalSpan = 3;
moveLabel = new Label(shell, SWT.CENTER | SWT.BORDER);
moveLabel = new Label(shell, SWT.CENTER);
moveLabel.setText("Alert Visualization Popup Message Dialog");
moveLabel.setLayoutData(gd);
moveLabel.setFont(labelFont);
@ -415,97 +437,90 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
* Create the labels at the top of the dialog.
*/
private void createTopLabels() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
topLabelComp = new Composite(shell, SWT.NONE);
GridLayout gl = new GridLayout(3, false);
gl.horizontalSpacing = 35;
topLabelComp.setLayout(gl);
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
topLabelComp.setLayoutData(gd);
topLabelComp.setBackground(display.getSystemColor(SWT.COLOR_RED));
sourceLbl = new Label(topLabelComp, SWT.BORDER);
sourceLbl.setText(sourceStr + statMsgArray.get(0).getSourceKey());
gd = new GridData(200, SWT.DEFAULT);
gd.verticalIndent = 10;
sourceLbl = new Label(topLabelComp, SWT.NONE);
sourceLbl.setText(sourceStr + statMsgArray.get(0).getSourceKey());
sourceLbl.setLayoutData(gd);
gd = new GridData(200, SWT.DEFAULT);
gd.verticalIndent = 10;
priorityLbl = new Label(topLabelComp, SWT.NONE);
priorityLbl = new Label(topLabelComp, SWT.BORDER);
priorityLbl.setText(priorityStr
+ statMsgArray.get(0).getPriority().ordinal());
priorityLbl.setLayoutData(gd);
gd = new GridData(200, SWT.DEFAULT);
gd.verticalIndent = 10;
categoryLbl = new Label(topLabelComp, SWT.NONE);
categoryLbl.setText(categoryStr + statMsgArray.get(0).getCategory());
categoryLbl.setLayoutData(gd);
priorityLbl.setLayoutData(gd);
/*
* If the expanded flag is false then hide the labels that display the
* Category/Source/Priority information.
*/
if (expanded == false) {
// Hide the message labels
((GridData) topLabelComp.getLayoutData()).exclude = true;
topLabelComp.setVisible(false);
shell.layout();
shell.pack();
}
categoryLbl = new Label(topLabelComp, SWT.BORDER);
categoryLbl.setText(categoryStr + statMsgArray.get(0).getCategory());
gd = new GridData(200, SWT.DEFAULT);
gd.verticalIndent = 10;
categoryLbl.setLayoutData(gd);
}
/**
* Create the message text control.
*/
private void createMessageControl() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
messageComp = new Composite(shell, SWT.NONE);
messageComp.setLayout(new GridLayout(1, false));
messageComp.setLayoutData(gd);
messageComp.setBackground(display.getSystemColor(SWT.COLOR_RED));
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
gd.heightHint = 20;
gd.widthHint = 920;
messageTF = new Text(messageComp, SWT.BORDER | SWT.MULTI | SWT.WRAP
| SWT.V_SCROLL);
messageTF.setLayoutData(gd);
messageTF.setText(statMsgArray.get(0).getMessage());
messageTF.setEditable(false);
messageTF.setText(statMsgArray.get(0).getMessage());
int preferredHeight = messageTF.computeSize(controlWidth, SWT.DEFAULT).y;
/*
* compute size to display only max initial lines
*/
int height = messageTF.getLineHeight() * MAX_INITIAL_LINES;
Rectangle initialSize = messageTF.computeTrim(0, 0, controlWidth,
height);
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.widthHint = initialSize.width;
gd.heightHint = Math.min(preferredHeight, initialSize.height);
gd.minimumHeight = gd.heightHint;
messageTF.setLayoutData(gd);
}
/**
* Create the action buttons for the dialog.
*/
private void createActionButtons() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
actionComp = new Composite(shell, SWT.NONE);
actionComp.setLayout(new GridLayout(7, false));
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
actionComp.setLayoutData(gd);
actionComp.setBackground(display.getSystemColor(SWT.COLOR_RED));
gd = new GridData(200, SWT.DEFAULT);
timeLbl = new Label(actionComp, SWT.NONE);
timeLbl = new Label(actionComp, SWT.BORDER);
timeLbl.setText(dateFormat.format(statMsgArray.get(0).getEventTime()));
gd = new GridData(200, SWT.DEFAULT);
timeLbl.setLayoutData(gd);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
fillerLbl = new Label(actionComp, SWT.NONE);
fillerLbl.setText("");
fillerLbl.setBackground(display.getSystemColor(SWT.COLOR_RED));
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
fillerLbl.setLayoutData(gd);
gd = new GridData(100, SWT.DEFAULT);
hideShowLogBtn = new Button(actionComp, SWT.PUSH);
hideShowLogBtn.setLayoutData(gd);
if (expanded == true) {
hideShowLogBtn.setText("Hide Log");
} else {
hideShowLogBtn.setText("Show Log");
}
hideShowLogBtn.setLayoutData(new GridData());
hideShowLogBtn.setText("Hide Log");
hideShowLogBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
@ -547,90 +562,69 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
hideDialogBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
Rectangle prevLocation = Display.getCurrent().getBounds();
av.setAlertPopupMsgPrvLocation(prevLocation);
shell.setVisible(false);
}
});
/*
* If the expanded flag is false then hide the Acknowledge Selected
* button.
*/
if (expanded == false) {
// Hide the Acknowledge Selected button
((GridData) ackSelectedBtn.getLayoutData()).exclude = true;
ackSelectedBtn.setVisible(false);
actionComp.layout();
actionComp.pack();
}
}
/**
* Create the message log list control.
*/
private void createMessageLogControl() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
logComp = new Composite(shell, SWT.NONE);
logComp.setLayout(new GridLayout(1, false));
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
logComp.setLayoutData(gd);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
Label dblClickLBl = new Label(logComp, SWT.BORDER | SWT.CENTER);
dblClickLBl
.setText("Double-click message to display more information:");
dblClickLBl.setFont(dblClickLblFont);
dblClickLBl.setFont(labelFont);
dblClickLBl.setForeground(display.getSystemColor(SWT.COLOR_DARK_BLUE));
dblClickLBl.setLayoutData(gd);
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.widthHint = 900;
gd.heightHint = 250;
msgLogList = new List(logComp, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
msgLogList.setFont(controlFont);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
Rectangle size = msgLogList.computeTrim(0, 0, controlWidth,
msgLogList.getItemHeight() * NUM_LIST_ITEMS);
gd.widthHint = size.width;
gd.heightHint = size.height;
gd.heightHint = (msgLogList.getItemHeight() * 10)
+ (msgLogList.getBorderWidth() * 2);
msgLogList.setLayoutData(gd);
msgLogList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
showSelectedListData();
}
});
detailsComp = new SimpleDetailsComp(logComp, SWT.NONE);
msgLogList.addMouseListener(new MouseListener() {
@Override
public void mouseDoubleClick(MouseEvent e) {
if (detailsComp.isVisible() == false) {
public void widgetDefaultSelected(SelectionEvent e) {
int delta = 0;
if (detailsComp.isVisible()) {
((GridData) detailsComp.getLayoutData()).exclude = true;
detailsComp.setVisible(false);
delta -= detailsComp.getSize().y;
} else {
int idx = msgLogList.getSelectionIndex();
if (idx < 0) {
return;
}
StatusMessage sm = statMsgArray.get(idx);
detailsComp.displayDetails(sm);
((GridData) detailsComp.getLayoutData()).exclude = false;
detailsComp.setVisible(true);
} else {
detailsComp.setVisible(false);
delta += detailsComp.getSize().y;
}
}
@Override
public void mouseDown(MouseEvent e) {
adjustHeight(delta);
}
@Override
public void mouseUp(MouseEvent e) {
}
});
if (expanded == false) {
((GridData) logComp.getLayoutData()).exclude = true;
logComp.setVisible(false);
shell.layout();
shell.pack();
}
detailsComp = new SimpleDetailsComp(shell, SWT.NONE);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
detailsComp.setLayoutData(gd);
msgLogList.add(getFormattedMessage(statMsgArray.get(0)));
msgLogList.select(0);
@ -641,46 +635,59 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
* Show/Hide the message log list.
*/
private void showHideLog() {
int delta = 0;
if (expanded == true) {
// Show the message labels
((GridData) topLabelComp.getLayoutData()).exclude = false;
topLabelComp.setVisible(true);
shell.layout();
shell.pack();
delta += topLabelComp.getSize().y;
// Show the Acknowledge Selected button
((GridData) ackSelectedBtn.getLayoutData()).exclude = false;
ackSelectedBtn.setVisible(true);
actionComp.layout();
actionComp.pack();
hideShowLogBtn.setText("Hide Log");
// Show the message log
((GridData) logComp.getLayoutData()).exclude = false;
logComp.setVisible(true);
shell.layout();
shell.pack();
hideShowLogBtn.setText("Hide Log");
delta += logComp.getSize().y;
} else {
// Hide the message labels
((GridData) topLabelComp.getLayoutData()).exclude = true;
topLabelComp.setVisible(false);
shell.layout();
shell.pack();
delta -= topLabelComp.getSize().y;
// Hide the Acknowledge Selected button
((GridData) ackSelectedBtn.getLayoutData()).exclude = true;
ackSelectedBtn.setVisible(false);
actionComp.layout();
actionComp.pack();
hideShowLogBtn.setText("Show Log");
// Hide the message log
detailsComp.setVisible(false);
if (this.first || detailsComp.isVisible()) {
((GridData) detailsComp.getLayoutData()).exclude = true;
detailsComp.setVisible(false);
delta -= detailsComp.getSize().y;
this.first = false;
}
((GridData) logComp.getLayoutData()).exclude = true;
logComp.setVisible(false);
shell.layout();
shell.pack();
hideShowLogBtn.setText("Show Log");
delta -= logComp.getSize().y;
}
actionComp.layout();
adjustHeight(delta);
}
private void adjustHeight(int delta) {
Point minSize = shell.getMinimumSize();
minSize.y += delta;
shell.setMinimumSize(minSize);
Point size = shell.getSize();
size.x += SWT_BUG_FACTOR;
size.y += delta + SWT_BUG_FACTOR;
shell.setSize(size);
}
/**
@ -701,10 +708,19 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
sourceLbl.setText(sourceStr + sm.getSourceKey());
timeLbl.setText(dateFormat.format(sm.getEventTime()));
messageTF.setText(sm.getMessage());
int desiredHeight = Math.min(MAX_INITIAL_LINES,
messageTF.getLineCount())
* messageTF.getLineHeight();
Rectangle clientArea = messageTF.getClientArea();
if (clientArea.height < desiredHeight) {
Rectangle trim = messageTF.computeTrim(clientArea.x, clientArea.y,
clientArea.width, desiredHeight);
Point oldSize = messageTF.getSize();
messageTF.setSize(oldSize.x, trim.height);
adjustHeight(trim.height - oldSize.y);
}
detailsComp.displayDetails(sm);
this.shell.pack();
}
/**
@ -747,7 +763,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
}
// Check if a message is not selected.
if (currentIndex < 0 || !expanded) {
if ((currentIndex < 0) || !expanded) {
if (msgLogList.getItemCount() > 0) {
msgLogList.select(0);
showSelectedListData();
@ -759,7 +775,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
// Check if the current index will go outside the array
// (it should never do this but check anyway...)
if (currentIndex > 0 && currentIndex == statMsgArray.size()) {
if ((currentIndex > 0) && (currentIndex == statMsgArray.size())) {
msgLogList.select(0);
showSelectedListData();
return;
@ -877,6 +893,8 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
messageComp.setBackground(bgColor);
actionComp.setBackground(bgColor);
fillerLbl.setBackground(bgColor);
logComp.setBackground(bgColor);
detailsComp.setBackground(bgColor);
}
/**
@ -890,18 +908,18 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
return;
}
boolean expandedForPromp = false;
boolean expandedForPrompt = false;
if (!expanded) {
expandedForPromp = expanded = true;
expandedForPrompt = expanded = true;
showHideLog();
}
showHideLog();
if (confirmPrompt) {
ConfirmationDlg cd = new ConfirmationDlg(shell,
"Are you sure you want to acknowledge all popup messages?",
SWT.ICON_QUESTION);
if (msgLogList != null && !msgLogList.isDisposed()) {
if ((msgLogList != null) && !msgLogList.isDisposed()) {
Rectangle logBounds = msgLogList.getBounds();
Point logDisplayOrigin = msgLogList.toDisplay(0, 0);
logBounds.x = logDisplayOrigin.x;
@ -912,7 +930,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
result = cd.open();
if (result != SWT.YES) {
if (result == SWT.CANCEL && expandedForPromp) {
if ((result == SWT.CANCEL) && expandedForPrompt) {
expanded = false;
showHideLog();
}
@ -951,17 +969,18 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
private void setInitialDialogLocation() {
if (dialogXY == null) {
Point minSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
shell.setMinimumSize(minSize);
int screenHeight = display.getBounds().height;
int screenWidth = display.getPrimaryMonitor().getBounds().width;
int newX = screenWidth / 2
- (shell.getChildren())[0].getBounds().width / 2;
int newY = (screenHeight / 2 - (shell.getChildren())[0].getBounds().height / 2) - 200;
Point size = minSize;
shell.setSize(size);
shell.setLocation(newX, newY);
dialogXY = new Point(newX, newY);
dialogXY = new Point((screenWidth - size.x) / 2,
(screenHeight - size.y) / 4);
shell.setLocation(dialogXY);
} else {
shell.setLocation(dialogXY);
}
@ -997,7 +1016,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
* @return True if open, false if not.
*/
public boolean dialogIsOpen() {
return (shell != null && !shell.isDisposed() && shell.isVisible());
return ((shell != null) && !shell.isDisposed() && shell.isVisible());
}
/**
@ -1042,7 +1061,7 @@ public class AlertPopupMessageDlg extends Dialog implements MouseMoveListener,
*/
@Override
public void mouseMove(MouseEvent e) {
if (origin != null && moveDialog == true) {
if ((origin != null) && (moveDialog == true)) {
// Move the dialog.
dialogLoc = display.map(shell, null, e.x, e.y);
dialogXY.x = dialogLoc.x - origin.x;

View file

@ -95,6 +95,7 @@ import com.raytheon.uf.viz.core.VizApp;
* then set the icon to the default image.
* 18 Mar 2015 4234 njensen Remove reference to non-working python
* 03 Jun 2015 4473 njensen Updated for new AlertvizJob API
* 29 Jun 2015 4311 randerso Reworking AlertViz dialogs to be resizable.
*
* </pre>
*
@ -377,8 +378,8 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
@Override
public void widgetSelected(SelectionEvent e) {
if (alertPopupDlg != null
&& alertPopupDlg.getNumberOfMessages() > 0) {
if ((alertPopupDlg != null)
&& (alertPopupDlg.getNumberOfMessages() > 0)) {
cancelTimer();
openAlertPopupDialog();
}
@ -437,20 +438,15 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
MenuItem viewLogMI = new MenuItem(trayItemMenu, SWT.NONE);
viewLogMI.setText("System Log...");
viewLogMI.addSelectionListener(new SelectionAdapter() {
boolean open = false;
SimpleLogViewer slv = null;
@Override
public void widgetSelected(SelectionEvent event) {
if (open) {
open = slv.focus(); // Do Nothing! It's open
} else {
open = true;
if ((slv == null) || slv.isDisposed()) {
slv = new SimpleLogViewer(shell);
slv.setText("System Log");
slv.open();
open = false;
} else {
slv.bringToTop();
}
}
});
@ -597,7 +593,7 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
* Show the Alert Visualization Configuration dialog.
*/
private void showConfigDialog() {
if (configDlg != null && !configDlg.isDisposed()) {
if ((configDlg != null) && !configDlg.isDisposed()) {
configDlg.close();
}
configDlg = new AlertVisConfigDlg(shell, alertMessageDlg, configData,
@ -640,7 +636,7 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
.hasMissing(statMsg))) {
Source source = configData.lookupSource("GDN_ADMIN");
RGB backgroundRBG = null;
if (source == null || source.getConfigurationItem() == null) {
if ((source == null) || (source.getConfigurationItem() == null)) {
backgroundRBG = ColorUtil.getColorValue("COLOR_YELLOW");
} else {
AlertMetadata am = source.getConfigurationItem().lookup(
@ -663,7 +659,7 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
}
} else {
if (cat.getCategoryName().equals(Constants.MONITOR)
|| amd.isText() == true) {
|| (amd.isText() == true)) {
alertMessageDlg.messageHandler(statMsg, amd, cat,
gConfig);
}
@ -689,8 +685,8 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
audioFile = getFullAudioFilePath(audioFile);
} else {
audioFile = statMsg.getAudioFile();
if (audioFile != null
&& (audioFile.trim().length() == 0 || audioFile
if ((audioFile != null)
&& ((audioFile.trim().length() == 0) || audioFile
.equals("NONE"))) {
audioFile = null;
}
@ -703,10 +699,9 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
// Pop-up message
if (amd.isPopup() == true) {
if (alertPopupDlg == null || alertPopupDlg.isDisposed() == true) {
if ((alertPopupDlg == null) || (alertPopupDlg.isDisposed() == true)) {
alertPopupDlg = new AlertPopupMessageDlg(shell, statMsg,
gConfig.isExpandedPopup(), this, amd.getBackground(),
this);
gConfig.isExpandedPopup(), this, amd.getBackground());
} else {
alertPopupDlg.addNewMessage(statMsg, amd);
}
@ -739,7 +734,7 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
if (!file.exists()) {
file = PathManagerFactory.getPathManager().getStaticFile(
"alertVizAudio/" + file.getName());
if (file == null || !file.exists()) {
if ((file == null) || !file.exists()) {
filename = null;
} else {
filename = file.getPath();
@ -752,7 +747,7 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
* Opens the alert pop-up dialog
*/
public void openAlertPopupDialog() {
if (alertPopupDlg != null && alertPopupDlg.dialogIsOpen() == true) {
if ((alertPopupDlg != null) && (alertPopupDlg.dialogIsOpen() == true)) {
alertPopupDlg.showDialog(true);
} else {
alertPopupDlg.open();
@ -849,7 +844,7 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
configData = ConfigurationManager.getInstance()
.getCurrentConfiguration();
configContext = ConfigurationManager.getInstance().getCurrentContext();
if (alertMessageDlg != null && showAlertDialogMI != null) {
if ((alertMessageDlg != null) && (showAlertDialogMI != null)) {
alertMessageDlg.setConfigData(configData);
if (configData.isMonitorLayoutChanged(prevConfigFile)) {
if (alertMessageDlg.reLayout()) {
@ -864,21 +859,6 @@ public class AlertVisualization implements ITimerAction, IAudioAction,
// }
}
/**
* Set the Alert Popup Message previous location.
*/
public void setAlertPopupMsgPrvLocation(Rectangle prevLocation) {
this.prevLocation = prevLocation;
}
/**
* Get the Alert Popup Message to restore the window to its previous
* location.
*/
public Rectangle getAlertPopupMsgPrvLocation() {
return this.prevLocation;
}
/**
* Get the number of text control composites.
*

View file

@ -29,7 +29,6 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.common.message.StatusMessage;
@ -40,7 +39,8 @@ import com.raytheon.uf.common.message.StatusMessage;
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Oct 9, 2008 chammack Initial creation
* Oct 09, 2008 chammack Initial creation
* Jun 29, 2015 4311 randerso Reworking AlertViz dialogs to be resizable.
* </pre>
*
* @author chammack
@ -49,10 +49,7 @@ import com.raytheon.uf.common.message.StatusMessage;
public class SimpleDetailsComp extends Composite {
/**
* Shell of the parent composite
*/
private Shell shell = null;
private static final int NUM_DETAIL_LINES = 13;
/**
* Actually contains text of details message, lives in textBox
@ -66,25 +63,22 @@ public class SimpleDetailsComp extends Composite {
*/
public SimpleDetailsComp(Composite parent, int style) {
super(parent, style);
this.shell = parent.getShell();
initComponents();
setVisible(false);
}
/**
* Lay out composite with StyledText
*/
private void initComponents() {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
setLayout(new GridLayout(1, false));
setLayoutData(gd);
GridLayout layout = new GridLayout(1, false);
setLayout(layout);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
gd.heightHint = 250;
st = new StyledText(this, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
st = new StyledText(this, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER
| SWT.WRAP);
st.setEditable(false);
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
gd.heightHint = (st.getLineHeight() * NUM_DETAIL_LINES)
+ (st.getBorderWidth() * 2);
st.setLayoutData(gd);
Menu popupMenu = new Menu(st);
@ -121,43 +115,10 @@ public class SimpleDetailsComp extends Composite {
if (sm == null) {
st.setText("");
} else {
StringBuilder sb = new StringBuilder();
// sb.append(sm.getMessage()).append("\n");
String details = sm.getDetails();
String[] lines = details.split("[\n]");
for (String line : lines) {
if (line.length() > 500) {
sb.append(line.substring(0, 500)).append(
"...text truncated\n");
} else {
sb.append(line).append("\n");
}
}
st.setText(sb.toString());
st.setText(sm.getDetails());
}
}
/**
* Override so we can exclude this composite from the layout when hidden
*/
@Override
public void setVisible(boolean visible) {
((GridData) this.getLayoutData()).exclude = !visible;
if (visible == true) {
((GridData) st.getLayoutData()).widthHint = getParent().getBounds().width - 46;
}
super.setVisible(visible);
shell.layout();
shell.pack();
}
/**
*
*/

View file

@ -26,12 +26,11 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@ -51,10 +50,15 @@ import com.raytheon.uf.common.message.StatusMessage;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.viz.alertviz.Activator;
import com.raytheon.uf.viz.alertviz.AlertvizException;
import com.raytheon.uf.viz.alertviz.AlertvizJob;
import com.raytheon.uf.viz.alertviz.Container;
import com.raytheon.uf.viz.alertviz.IAlertArrivedCallback;
import com.raytheon.uf.viz.alertviz.LogUtil;
import com.raytheon.uf.viz.alertviz.LogUtil.Order;
import com.raytheon.uf.viz.alertviz.SystemStatusHandler;
import com.raytheon.uf.viz.alertviz.config.AlertMetadata;
import com.raytheon.uf.viz.alertviz.config.Category;
import com.raytheon.uf.viz.alertviz.config.TrayConfiguration;
/**
* Implements a basic log viewer capability
@ -65,6 +69,8 @@ import com.raytheon.uf.viz.alertviz.SystemStatusHandler;
* ------------ ---------- ----------- --------------------------
* Sep 30, 2008 1433 chammack Initial creation
* Jun 02, 2015 4473 njensen Cleaned up warnings
* Jul 01, 2015 4473 njensen Fix update of table on alert arrival
* Jun 29, 2015 4311 randerso Reworking AlertViz dialogs to be resizable.
*
* </pre>
*
@ -72,69 +78,67 @@ import com.raytheon.uf.viz.alertviz.SystemStatusHandler;
* @version 1.0
*/
public class SimpleLogViewer extends Dialog {
public class SimpleLogViewer extends Dialog implements IAlertArrivedCallback {
private Display display;
/**
*
*/
private Shell shell;
/**
*
*/
private SimpleDetailsComp sdb;
private SimpleDetailsComp detailsComp;
/**
*
*/
private Button showLog;
/**
*
*/
private Table reference;
/**
*
*/
int[] range;
private Table table;
private Color yellow;
private Color red;
private Color orange;
private Color black;
boolean first;
/**
*
* @param parent
*/
public SimpleLogViewer(Shell parent) {
super(parent, SWT.NONE);
first = true;
display = parent.getDisplay();
// Create a new shell object and set the text for the dialog.
shell = new Shell(display, SWT.DIALOG_TRIM | SWT.MIN | SWT.TITLE
| SWT.RESIZE);
shell.setText("System Log");
initializeComponents();
}
/**
* set focus to the dialog
*
* @return false if not open or disposed, true otherwise
* @return true if shell is null or disposed;
*/
public boolean focus() {
if (shell == null || shell.isDisposed()) {
return false;
} else {
public boolean isDisposed() {
return ((shell != null) && shell.isDisposed());
}
/**
* Bring dialog to the top
*/
public void bringToTop() {
if ((shell != null) && !shell.isDisposed()) {
shell.setVisible(true);
shell.forceFocus();
return true;
shell.forceActive();
}
}
/**
* Opens the dialog (makes visible).
*
* @return Null
*/
public Object open() {
// Create a new shell object and set the text for the dialog.
Shell parent = getParent();
// shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.MIN | SWT.RESIZE);
shell = new Shell(parent.getDisplay(), SWT.DIALOG_TRIM | SWT.MIN
| SWT.TITLE | SWT.RESIZE);
shell.setText(getText());
/* TODO: Max Code: */
private void initializeComponents() {
GridLayout mainLayout = new GridLayout(1, true);
mainLayout.marginHeight = 0;
mainLayout.marginWidth = 0;
@ -143,15 +147,7 @@ public class SimpleLogViewer extends Dialog {
GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, true, true);
shell.setLayoutData(gd);
// shell.setLayout(new GridLayout(1, false));
// shell.setSize(800, 400);
// shell.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
// | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
// | GridData.VERTICAL_ALIGN_FILL));
final Table table = new Table(shell, SWT.BORDER | SWT.VIRTUAL);
reference = table;
table = new Table(shell, SWT.BORDER | SWT.VIRTUAL);
final TableColumn[] columns = new TableColumn[] {
new TableColumn(table, SWT.NONE),
new TableColumn(table, SWT.NONE),
@ -159,10 +155,6 @@ public class SimpleLogViewer extends Dialog {
new TableColumn(table, SWT.NONE),
new TableColumn(table, SWT.NONE) };
// table.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
// | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
// | GridData.VERTICAL_ALIGN_FILL));
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
gd.widthHint = 800;
gd.heightHint = 400;
@ -179,47 +171,39 @@ public class SimpleLogViewer extends Dialog {
columns[3].setWidth(100);
columns[4].setText("Message");
columns[4].setWidth(100);
final int[] range;
final int sz;
int sz = 0;
try {
range = SystemStatusHandler.getCurrentRange();
this.range = range;
sz = range[1] - range[0];
if ((range[0] == 0) && (range[1] == 0)) {
// database is empty
sz = 0;
} else {
sz = (range[1] - range[0]) + 1;
}
} catch (AlertvizException e2) {
Container
.logInternal(
Priority.ERROR,
"SimpleLogViewer: exception getting current range from SystemStatusHandler.",
e2);
return null;
}
table.setSortColumn(columns[0]);
table.setSortDirection(SWT.UP);
final Color red = new Color(Display.getCurrent(), new RGB(255, 0, 0));
final Color yellow = new Color(Display.getCurrent(), new RGB(255, 255,
0));
final Color orange = new Color(Display.getCurrent(), new RGB(255, 128,
0));
final Color black = new Color(Display.getCurrent(), new RGB(0, 0, 0));
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseDoubleClick(MouseEvent e) {
showHideLog();
}
});
red = new Color(display, new RGB(255, 0, 0));
yellow = new Color(Display.getCurrent(), new RGB(255, 255, 0));
orange = new Color(display, new RGB(255, 128, 0));
black = new Color(display, new RGB(0, 0, 0));
table.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int idx = table.getSelectionIndex();
StatusMessage sm = null;
try {
StatusMessage sm = SystemStatusHandler.retrieveByPk(idx
+ range[0]);
sdb.displayDetails(sm);
sm = SystemStatusHandler.retrieveByPk(idx + range[0]);
} catch (Exception e1) {
Container
.logInternal(
@ -227,6 +211,12 @@ public class SimpleLogViewer extends Dialog {
"SimpleLogViewer: exception retrieving StatusMessage by key from SystemStatusHandler: "
+ (idx + range[0]), e1);
}
detailsComp.displayDetails(sm);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
showHideLog();
}
});
@ -332,19 +322,52 @@ public class SimpleLogViewer extends Dialog {
}
});
sdb = new SimpleDetailsComp(shell, SWT.NONE);
detailsComp = new SimpleDetailsComp(shell, SWT.NONE);
gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false);
detailsComp.setLayoutData(gd);
}
@Override
public void alertArrived(StatusMessage statusMessage,
AlertMetadata alertMetadata, Category category,
TrayConfiguration globalConfiguration) {
if (!table.isDisposed()) {
int count = table.getItemCount();
table.setItemCount(count + 1);
}
}
/**
* Opens the dialog (makes visible).
*
* @return null
*/
public Object open() {
Point minSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
shell.setMinimumSize(minSize);
Point size = minSize;
shell.setSize(size);
showHideLog();
AlertvizJob.getInstance().addAlertArrivedCallback(this);
shell.pack();
shell.open();
table.showItem(table.getItem(table.getItemCount() - 1));
table.select(table.getItemCount() - 1);
// Wait until the shell is disposed.
Display display = parent.getDisplay();
Display display = shell.getDisplay();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
AlertvizJob.getInstance().removeAlertArrivedCallback(this);
table.dispose();
red.dispose();
yellow.dispose();
@ -358,26 +381,27 @@ public class SimpleLogViewer extends Dialog {
*
*/
private void showHideLog() {
int idx = reference.getSelectionIndex();
if (idx < 0) {
return;
}
try {
StatusMessage sm = SystemStatusHandler.retrieveByPk(idx + range[0]);
if (sdb.isVisible() == false) {
sdb.setVisible(true);
sdb.displayDetails(sm);
showLog.setText("Hide Log...");
} else {
sdb.setVisible(false);
showLog.setText("Show Log...");
}
} catch (AlertvizException e1) {
Container
.logInternal(
Priority.ERROR,
"SimpleLogViewer: exception retrieving StatusMessage by key from SystemStatusHandler: "
+ (idx + range[0]), e1);
int delta = 0;
if (first || detailsComp.isVisible()) {
showLog.setText("Show Log...");
((GridData) detailsComp.getLayoutData()).exclude = true;
detailsComp.setVisible(false);
delta -= detailsComp.getSize().y;
first = false;
} else {
showLog.setText("Hide Log...");
((GridData) detailsComp.getLayoutData()).exclude = false;
detailsComp.setVisible(true);
delta += detailsComp.getSize().y;
}
Point minSize = shell.getMinimumSize();
minSize.y += delta;
shell.setMinimumSize(minSize);
Point size = shell.getSize();
size.y += delta;
shell.setSize(size);
}
}

View file

@ -2,9 +2,20 @@
<!-- Only define when not wanting to use the UF Standard.
<property scope="context" name="log.message.pattern" value="%-5p %d [%t] %c{0}: %m%n"/>
-->
<timestamp key="startTime" datePattern="yyyyMMdd_HHmmss" />
<define name="adminLogFile" class="com.raytheon.uf.common.logback.LogFilePropertyDefiner" >
<directory>${LOGDIR}</directory>
<name>alertviz_${startTime}_admin.log</name>
</define>
<define name="consoleLogFile" class="com.raytheon.uf.common.logback.LogFilePropertyDefiner" >
<directory>${LOGDIR}</directory>
<name>alertviz_${startTime}_console.log</name>
</define>
<!-- general application log -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="com.raytheon.uf.common.logback.encoder.UFStdEncoder"/>
<!-- In eclipse InvertedThresholdFilter allows different color display for console and errConsole. -->
<filter class="com.raytheon.uf.common.logback.filter.InvertedThresholdFilter">
<level>INFO</level>
</filter>
@ -18,20 +29,16 @@
<encoder class="com.raytheon.uf.common.logback.encoder.UFStdEncoder"/>
</appender>
<appender name="AlertVizAdminLogAppender" class="com.raytheon.uf.common.logback.appender.EnvConfigurableRollingFileAppender">
<!-- file and fileNamePattern will be overridden by the env variable if present, but are required by logback -->
<file>alertviz-admin.log</file>
<envLogVar>LOGFILE_ALERTVIZ</envLogVar>
<rollingPolicy class="com.raytheon.uf.common.logback.policy.EnvConfigurableFixedWindowRollingPolicy">
<fileNamePattern>alertviz-admin.log%i</fileNamePattern>
<envLogVar>LOGFILE_ALERTVIZ</envLogVar>
<minIndex>1</minIndex>
<maxIndex>5</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>2GB</maxFileSize>
</triggeringPolicy>
<append>true</append>
<appender name="consoleLog" class="com.raytheon.uf.common.logback.appender.ConsoleFileAppender">
<encoder class="com.raytheon.uf.common.logback.encoder.UFStdEncoder"/>
<file>${consoleLogFile}</file>
<filter class="com.raytheon.uf.common.logback.filter.InvertedThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<appender name="AlertVizAdminLogAppender" class="ch.qos.logback.core.FileAppender">
<file>${adminLogFile}</file>
<encoder class="com.raytheon.uf.common.logback.encoder.UFStdEncoder"/>
</appender>
@ -71,5 +78,6 @@
<level value="INFO"/>
<appender-ref ref="console"/>
<appender-ref ref="errConsole"/>
<appender-ref ref="consoleLog"/>
</root>
</configuration>

View file

@ -75,10 +75,11 @@ import com.raytheon.uf.viz.core.VizApp;
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 4, 2008 1433 chammack Initial creation
* Jun 3, 2013 2026 randerso Improve error handling
* May 5, 2015 4473 mschenke Major refactor
* Jun 1, 2015 4473 njensen Major refactor, removed send ability
* Sep 04, 2008 1433 chammack Initial creation
* Jun 03, 2013 2026 randerso Improve error handling
* May 05, 2015 4473 mschenke Major refactor
* Jun 01, 2015 4473 njensen Major refactor, removed send ability
* Jun 29, 2015 4473 njensen Register notification observer on start
*
* </pre>
*
@ -178,6 +179,7 @@ public class AlertvizJob extends Job implements AlertService {
this.broker.setPersistent(false);
this.broker.setUseJmx(false);
this.port = port;
AlertVizNotificationObserver.registerAlertVizNotificationObserver();
String localIP = "localhost";
try {

View file

@ -28,6 +28,7 @@ import java.util.Map;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
@ -66,6 +67,7 @@ import com.raytheon.uf.viz.collaboration.ui.data.TreeObjectContainer;
* Mar 06, 2014 2848 bclement get venueName directly from session
* Jun 12, 2014 3267 bclement fixed missing null-check for outdated UI info
* Oct 08, 2014 3705 bclement replaced checks for SessionGroupContainer with TreeObjectContainer
* Jun 23, 2015 4563 mapeters bold/color users in contacts list if logged-in
*
* </pre>
*
@ -86,6 +88,7 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
return connection.getContactsManager().getPresence(user);
}
@Override
protected String getDisplayName(UserId user) {
return getLocalAlias(user);
}
@ -136,7 +139,6 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
}
return rval;
}
};
private List<ILabelProviderListener> listeners;
@ -159,7 +161,7 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
if (element instanceof UserId) {
return userLabelProvider.getImage(element);
} else if (element instanceof RosterEntry) {
return userLabelProvider.getImage((RosterEntry) element);
return userLabelProvider.getImage(element);
} else if (element instanceof RosterGroup) {
key = "roster_group";
} else if (element instanceof SharedGroup) {
@ -168,7 +170,7 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
// key = "session_group";
} else if (element instanceof TreeObjectContainer) {
key = ((TreeObjectContainer) element).getIcon();
}
}
if (imageMap.get(key) == null && !key.equals("")) {
imageMap.put(key, CollaborationUtils.getNodeImage(key));
@ -183,7 +185,7 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
} else if (element instanceof SharedGroup) {
return ((SharedGroup) element).getName();
} else if (element instanceof RosterEntry) {
return userLabelProvider.getText((RosterEntry) element);
return userLabelProvider.getText(element);
} else if (element instanceof TreeObjectContainer) {
return ((TreeObjectContainer) element).getLabel();
} else if (element instanceof UserId) {
@ -211,10 +213,13 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
@Override
public Font getFont(Object element) {
if (element instanceof RosterGroup || element instanceof SharedGroup
|| element instanceof TreeObjectContainer) {
// for this case do nothing, as it is not the top level of
// session groups
boolean isGroupTitle = element instanceof RosterGroup
|| element instanceof SharedGroup
|| element instanceof TreeObjectContainer;
boolean isAvailableUser = element instanceof RosterEntry
&& userLabelProvider.getPresence(
userLabelProvider.convertObject(element)).isAvailable();
if (isGroupTitle || isAvailableUser) {
if (boldFont == null) {
Font currFont = Display.getCurrent().getSystemFont();
boldFont = new Font(Display.getCurrent(), currFont.toString(),
@ -225,6 +230,17 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
return null;
}
@Override
public Color getForeground(Object element) {
if (element instanceof RosterEntry) {
UserId user = userLabelProvider.convertObject(element);
if (userLabelProvider.getPresence(user).isAvailable()) {
return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
}
}
return null;
}
/**
* Gets the tooltip text on the tree that this is a label provider for
*/
@ -234,7 +250,7 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
if (element instanceof UserId) {
return userLabelProvider.getToolTipText(element);
} else if (element instanceof RosterEntry) {
return userLabelProvider.getToolTipText((RosterEntry) element);
return userLabelProvider.getToolTipText(element);
}
// builds the tooltip text for the session group
// portion of the view
@ -242,10 +258,8 @@ public class UsersTreeLabelProvider extends ColumnLabelProvider {
IVenueSession sessGroup = (IVenueSession) element;
IVenue venue = sessGroup.getVenue();
builder.append("ID: ").append(venue.getId());
builder.append("\nName: ").append(venue.getName())
.append("\n");
builder.append("Subject: ").append(venue.getSubject())
.append("\n");
builder.append("\nName: ").append(venue.getName()).append("\n");
builder.append("Subject: ").append(venue.getSubject()).append("\n");
builder.append("Participants: ")
.append(venue.getParticipantCount());
return builder.toString();

View file

@ -24,6 +24,7 @@ import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.handlers.HandlerUtil;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException;
import com.raytheon.uf.common.status.IUFStatusHandler;
@ -49,6 +50,8 @@ import com.raytheon.viz.ui.dialogs.localization.VizLocalizationFileListDlg.Mode;
* Jul 8, 2008 #1183 chammack Migrate to new localization
* Oct 16, 2012 #1229 rferrel Changes for non-blocking VizLocalizationFileListDlg.
* Jun 02, 2015 #4401 bkowal Updated to use {@link VizLocalizationFileListDlg}.
* Jun 30, 2015 #4401 bkowal Specify the localization type when constructing a
* {@link VizLocalizationFileListDlg}.
*
* </pre>
*
@ -74,7 +77,8 @@ public class DeleteAWIPSProcedure extends AbstractHandler {
|| listDlg.isDisposed()) {
listDlg = new VizLocalizationFileListDlg("Delete Procedure",
HandlerUtil.getActiveShell(event), Mode.DELETE,
ProcedureDlg.PROCEDURES_DIR, "procedures");
ProcedureDlg.PROCEDURES_DIR, "procedures",
LocalizationType.CAVE_STATIC);
listDlg.setCloseCallback(new ICloseCallback() {
@Override

View file

@ -26,6 +26,7 @@ import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.ui.handlers.HandlerUtil;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.LocalizationUtil;
import com.raytheon.uf.common.status.IUFStatusHandler;
@ -35,6 +36,7 @@ import com.raytheon.uf.viz.d2d.ui.dialogs.procedures.ProcedureDlg;
import com.raytheon.viz.ui.VizWorkbenchManager;
import com.raytheon.viz.ui.actions.LoadPerspectiveHandler;
import com.raytheon.viz.ui.dialogs.ICloseCallback;
import com.raytheon.viz.ui.dialogs.localization.VizLocalizationFileListDlg;
import com.raytheon.viz.ui.dialogs.localization.VizOpenLocalizationFileListDlg;
/**
@ -52,6 +54,8 @@ import com.raytheon.viz.ui.dialogs.localization.VizOpenLocalizationFileListDlg;
* Jun 07, 2013 2074 mnash Don't open the dialog if no procedures are deserialized
* Aug 11, 2014 3480 bclement added logging
* Jun 02, 2015 #4401 bkowal Updated to use {@link VizOpenLocalizationFileListDlg}.
* Jun 30, 2015 #4401 bkowal Specify the localization type when constructing a
* {@link VizOpenLocalizationFileListDlg}.
* </pre>
*
* @author chammack
@ -76,7 +80,8 @@ public class OpenAWIPSProcedure extends AbstractHandler {
if (dialog == null || dialog.getShell() == null || dialog.isDisposed()) {
dialog = new VizOpenLocalizationFileListDlg("Open Procedure",
HandlerUtil.getActiveShell(event),
ProcedureDlg.PROCEDURES_DIR, "procedures");
ProcedureDlg.PROCEDURES_DIR, "procedures",
LocalizationType.CAVE_STATIC);
dialog.setCloseCallback(new ICloseCallback() {
@Override

View file

@ -28,6 +28,7 @@ import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.viz.ui.dialogs.localization.VizLocalizationFileListDlg;
/**
@ -43,6 +44,7 @@ import com.raytheon.viz.ui.dialogs.localization.VizLocalizationFileListDlg;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 2, 2015 4401 bkowal Initial creation
* Jun 30, 2015 4401 bkowal Specify the localization level during construction.
*
* </pre>
*
@ -67,7 +69,8 @@ public class ProcedureListFileDlg extends VizLocalizationFileListDlg {
*/
public ProcedureListFileDlg(String title, Shell parent, Mode mode,
String localizationDirectory) {
super(title, parent, mode, localizationDirectory, "procedures");
super(title, parent, mode, localizationDirectory, "procedures",
LocalizationType.CAVE_STATIC);
}
@Override

View file

@ -4,9 +4,9 @@
<extension
point="com.raytheon.viz.ui.contextualMenu">
<contextualMenu
actionClass="com.raytheon.uf.viz.damagepath.ImportFromDistanceSpeedAction"
actionClass="com.raytheon.uf.viz.damagepath.NewTornadoDamagePathAction"
capabilityClass="com.raytheon.uf.viz.damagepath.DamagePathLayer"
name="Import from Distance Speed Tool"
name="New Tornado Damage Path"
sortID="4">
</contextualMenu>
<contextualMenu

View file

@ -83,6 +83,7 @@ import com.vividsolutions.jts.geom.Polygon;
* initInternal.
* Jun 18, 2015 4354 dgilling Allow each polygon to have their own
* properties.
* Jul 01, 2015 4375 dgilling Fix setDefaultPolygon.
*
* </pre>
*
@ -175,7 +176,7 @@ public class DamagePathLayer<T extends DamagePathResourceData> extends
Polygon polygon = PolygonUtil.makeDefaultPolygon(getResourceContainer()
.getActiveDisplayPane().getRenderableDisplay());
DrawablePolygon drawablePolygon = new DamagePathPolygon(polygon, this);
polygons.add(0, drawablePolygon);
super.resetPolygons(Arrays.asList(drawablePolygon));
}
@Override

View file

@ -26,7 +26,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
@ -38,7 +37,6 @@ import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.Name;
import com.raytheon.uf.common.json.JsonException;
import com.raytheon.uf.common.json.geo.BasicJsonService;
import com.raytheon.uf.common.json.geo.GeoJsonMapUtil;
import com.raytheon.uf.common.json.geo.IGeoJsonService;
import com.raytheon.uf.common.json.geo.SimpleGeoJsonService;
@ -47,7 +45,6 @@ import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.util.Pair;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.operation.valid.IsValidOp;
/**
* Loads a damage path GeoJSON-formatted file from either local disk or the
@ -62,6 +59,10 @@ import com.vividsolutions.jts.operation.valid.IsValidOp;
* Jun 05, 2015 #4375 dgilling Initial creation
* Jun 18, 2015 #4354 dgilling Support FeatureCollections so each polygon
* can have its own properties.
* Jun 30, 2015 #4354 dgilling Remove unnecessary back compat code for
* 15.1 version of damage path tool.
* Jul 01, 2015 #4375 dgilling Remove isValid check to imported
* polygons.
*
* </pre>
*
@ -71,12 +72,8 @@ import com.vividsolutions.jts.operation.valid.IsValidOp;
public final class DamagePathLoader {
private static final String UNSUPPORTED_GEOJSON_TYPE = "Damage path file is unsupported GeoJSON object type %s. This tool only supports Feature and Geometry objects.";
private static final String UNSUPPORTED_GEOM_TYPE = "Damage path file contains invalid geometry type %s at geometry index %d. Must only contain Polygons.";
private static final String INVALID_POLYGON = "Damage path file contains an invalid Polyon at index %d: %s";
private final Collection<Pair<Polygon, Map<String, String>>> damagePathData;
public DamagePathLoader(LocalizationFile locFile)
@ -119,85 +116,6 @@ public final class DamagePathLoader {
}
private void loadFromInputStream(final InputStream is) throws JsonException {
Geometry deserializedGeom = null;
Map<String, String> deserializedProps = Collections.emptyMap();
GeoJsonMapUtil geoJsonUtil = new GeoJsonMapUtil();
/*
* For compatibility with any users that may have an autosaved damage
* path file from previous builds, we'll support deserializing Geometry,
* Feature and FeatureCollection GeoJSON types.
*
* TODO: remove this code for code that just expects the file to always
* be a FeatureCollection.
*/
Map<String, Object> jsonObject = (Map<String, Object>) new BasicJsonService()
.deserialize(is, LinkedHashMap.class);
String geoJsonType = jsonObject.get(GeoJsonMapUtil.TYPE_KEY).toString();
if (geoJsonType.equals(GeoJsonMapUtil.FEATURE_COLL_TYPE)) {
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = geoJsonUtil
.populateFeatureCollection(jsonObject);
populateDataFromFeatureCollection(featureCollection);
return;
} else if (geoJsonType.equals(GeoJsonMapUtil.FEATURE_TYPE)) {
SimpleFeature feature = geoJsonUtil.populateFeature(jsonObject);
deserializedGeom = (Geometry) feature.getDefaultGeometry();
Name defaultGeomAttrib = feature.getDefaultGeometryProperty()
.getName();
deserializedProps = new LinkedHashMap<>();
deserializedProps.put(GeoJsonMapUtil.ID_KEY, feature.getID());
for (Property p : feature.getProperties()) {
if (!defaultGeomAttrib.equals(p.getName())) {
deserializedProps.put(p.getName().toString(), p.getValue()
.toString());
}
}
} else if (isGeometryType(geoJsonType)) {
deserializedGeom = geoJsonUtil.populateGeometry(jsonObject);
} else {
throw new JsonException(String.format(UNSUPPORTED_GEOJSON_TYPE,
geoJsonType));
}
int numGeometries = deserializedGeom.getNumGeometries();
for (int i = 0; i < numGeometries; i++) {
Geometry geomN = deserializedGeom.getGeometryN(i);
if (geomN instanceof Polygon) {
Polygon newPolygon = (Polygon) geomN;
IsValidOp validator = new IsValidOp(newPolygon);
if (validator.isValid()) {
Pair<Polygon, Map<String, String>> polygonAndProps = new Pair<>(
newPolygon, deserializedProps);
damagePathData.add(polygonAndProps);
} else {
throw new JsonException(String.format(INVALID_POLYGON, i,
validator.getValidationError()));
}
} else {
throw new JsonException(String.format(UNSUPPORTED_GEOM_TYPE,
geomN.getGeometryType(), i));
}
}
}
private boolean isGeometryType(String geoJsonType) {
return ((GeoJsonMapUtil.GEOM_COLL_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.LINE_STR_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.MULT_LINE_STR_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.MULT_POINT_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.MULT_POLY_TYPE.equals(geoJsonType))
|| (GeoJsonMapUtil.POINT_TYPE.equals(geoJsonType)) || (GeoJsonMapUtil.POLY_TYPE
.equals(geoJsonType)));
}
/*
* TODO: Replace loadFromInputStream with this method when we no longer
* desire supporting the version 15.1 GeoJSON formatted damage path files.
*/
@SuppressWarnings("unused")
private void loadFromInputStreamFuture(final InputStream is)
throws JsonException {
IGeoJsonService json = new SimpleGeoJsonService();
FeatureCollection<SimpleFeatureType, SimpleFeature> featureCollection = json
.deserializeFeatureCollection(is);
@ -215,12 +133,6 @@ public final class DamagePathLoader {
Geometry geom = (Geometry) feature.getDefaultGeometry();
if (geom instanceof Polygon) {
Polygon newPolygon = (Polygon) geom;
IsValidOp validator = new IsValidOp(newPolygon);
if (!validator.isValid()) {
throw new JsonException(String.format(INVALID_POLYGON,
featureIdx, validator.getValidationError()));
}
Map<String, String> properties = new LinkedHashMap<>();
Name defaultGeomAttrib = feature
.getDefaultGeometryProperty().getName();

View file

@ -23,7 +23,6 @@ import java.util.Collections;
import java.util.Map;
import com.raytheon.uf.viz.drawing.polygon.DrawablePolygon;
import com.raytheon.uf.viz.drawing.polygon.PolygonLayer;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Polygon;
@ -37,6 +36,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 18, 2015 #4354 dgilling Initial creation
* Jun 30, 2015 #4354 dgilling Force setProperties to trigger a save.
*
* </pre>
*
@ -51,23 +51,23 @@ public class DamagePathPolygon extends DrawablePolygon {
private Map<String, String> properties;
public DamagePathPolygon(PolygonLayer<?> polygonLayer) {
super(polygonLayer);
public DamagePathPolygon(DamagePathLayer<?> layer) {
super(layer);
this.properties = DEFAULT_PROPS;
}
public DamagePathPolygon(Polygon polygon, PolygonLayer<?> polygonLayer) {
this(polygon, DEFAULT_PROPS, polygonLayer);
public DamagePathPolygon(Polygon polygon, DamagePathLayer<?> layer) {
this(polygon, DEFAULT_PROPS, layer);
}
public DamagePathPolygon(Polygon polygon, Map<String, String> properties,
PolygonLayer<?> polygonLayer) {
super(polygon, polygonLayer);
DamagePathLayer<?> layer) {
super(polygon, layer);
this.properties = properties;
}
public DamagePathPolygon(Coordinate[] coords, PolygonLayer<?> polygonLayer) {
super(coords, polygonLayer);
public DamagePathPolygon(Coordinate[] coords, DamagePathLayer<?> layer) {
super(coords, layer);
this.properties = DEFAULT_PROPS;
}
@ -87,5 +87,6 @@ public class DamagePathPolygon extends DrawablePolygon {
public void setProperties(Map<String, String> properties) {
this.properties = properties;
((DamagePathLayer<?>) polygonLayer).scheduleSaveJob();
}
}

View file

@ -19,67 +19,89 @@
**/
package com.raytheon.uf.viz.damagepath;
import java.awt.geom.Point2D;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import javax.measure.converter.UnitConverter;
import javax.measure.quantity.Length;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.geotools.referencing.GeodeticCalculator;
import com.raytheon.uf.common.dataplugin.radar.RadarStation;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.viz.awipstools.common.stormtrack.AbstractStormTrackResource;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState;
import com.raytheon.viz.awipstools.common.stormtrack.StormTrackState.StormCoord;
import com.raytheon.viz.awipstools.ui.layer.InteractiveBaselinesLayer.Baseline;
import com.raytheon.viz.radar.util.StationUtils;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
/**
* Utility class for Damage Paths.
*
*
* <pre>
*
*
* SOFTWARE HISTORY
*
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 23, 2015 3977 nabowle Initial creation
* Mar 26, 2015 3977 nabowle Limit distance to avoid polar errors. Log
* skipped points.
* Apr 01, 2015 3977 nabowle rename the status handler.
*
* Jun 18, 2015 3977 nabowle Fix buffering. Renamed mehtods to
* specify that they're for Tornados.
* Jun 25, 2015 3977 nabowle Redo inner-point buffering for use with
* Interactive Baselines.
*
* </pre>
*
*
* @author nabowle
* @version 1.0
*/
public class DamagePathUtils {
/**
* The number of degrees between points at the ends of a Tornado Damage Path
* Buffer.
*/
private static final double END_DEGREE_DIFF = 30.0D;
/** Upper degree boundary to define a sharp angle. */
private static final double SHARP_ANGLE = 100;
/** Lower degree boundary when a sharp angle straddles 0 degrees. */
private static final double SHARP_ANGLE_INV = 360 - SHARP_ANGLE;
private static final IUFStatusHandler statusHandler = UFStatus
.getHandler(DamagePathUtils.class);
/** The unit for the uncertainty algorithm. */
private static Unit<Length> TARGET_UNIT = NonSI.MILE;
/** Convert miles for the algorithm to meters. */
private static UnitConverter TO_METERS = NonSI.MILE
.getConverterTo(SI.METER);
/** Convert meters returned the GeodeticCalculator to the desired unit. */
private static UnitConverter METERS_TO = SI.METER
.getConverterTo(TARGET_UNIT);
/*
* Pre-convert algorithm constants to meters to prevent having to convert
* back and forth.
*/
private static final double ONE_TENTH_MILE = TO_METERS.convert(0.1);
private static final double THREE_TENTHS_MILE = TO_METERS.convert(0.3);
private static final double FORTY_MILES = TO_METERS.convert(40.0);
private static final double EIGHTY_MILES = TO_METERS.convert(80.0);
/**
* Maximum distance of a point to the radar station to use when estimating a
* damage path polygon. Any farther point will be ignored.
* damage path polygon. Any farther point will be ignored. Based on radar
* max extent
*/
private static final double MAX_DISTANCE = NonSI.MILE.getConverterTo(
TARGET_UNIT).convert(300.0); // Based on radar max extent
private static final double MAX_DISTANCE = TO_METERS.convert(300.0);
private DamagePathUtils() {
super();
@ -87,129 +109,405 @@ public class DamagePathUtils {
/**
* Estimates the damage path polygon for a storm track.
* Estimates a Tornado damage path polygon for a baseline.
*
* @param stormTrack
* The storm track to create a damage path for.
* @return The estimated damage path polygon for a storm track.
* @param baseline
* The baseline to create a tornado damage path for.
* @return The estimated tornado damage path polygon for a baseline.
*/
public static Polygon estimateDamagePath(
AbstractStormTrackResource stormTrack) {
StormTrackState stState = stormTrack.getStormTrackState();
public static Polygon estimateTornadoDamagePath(Baseline baseline) {
Coordinate[] coords = baseline.line.getCoordinates();
RadarStation station = StationUtils.getInstance().getHomeRadarStation();
GeometryFactory gf = new GeometryFactory();
List<StormTrackState.StormCoord> skippedCoords = new ArrayList<>();
Geometry damagePathBuffer = createBuffer(stState.timePoints, station,
gf, null, skippedCoords);
damagePathBuffer = createBuffer(stState.futurePoints, station, gf,
damagePathBuffer, skippedCoords);
List<Coordinate> skippedCoords = new ArrayList<>();
List<Coordinate> validCoords = new ArrayList<>();
GeodeticCalculator gc = new GeodeticCalculator();
filterCoords(coords, station, skippedCoords, validCoords,
gc);
if (!skippedCoords.isEmpty()) {
StringBuilder sb = new StringBuilder();
sb.append("Skipped the following Storm Coordinates because they ")
sb.append(
"Skipped the following Coordinates for Baseline "
+ baseline.name + " because they ")
.append("are out of range of the radar station. ");
for (StormTrackState.StormCoord coord : skippedCoords) {
sb.append("(").append(coord.time.toString()).append(", ")
.append(coord.coord.x).append(", ")
.append(coord.coord.y).append(") ");
for (Coordinate coord : skippedCoords) {
sb.append("(").append(coord.x).append(", ").append(coord.y)
.append(") ");
}
statusHandler.info(sb.toString());
}
/*
* user likely tried to import before creating track or entire track is
* outside of the max range.
*/
if (damagePathBuffer == null) {
if (validCoords.isEmpty()) {
String suggestion;
if (skippedCoords.isEmpty()) {
suggestion = "Make sure the storm track is initialized.";
suggestion = "Make sure the baseline is initialized.";
} else {
suggestion = "Make sure the storm track is within range of the radar station.";
suggestion = "Make sure the baseline is within range of the radar station.";
}
statusHandler
.warn("Could not create a Damage Path polygon for the storm track. "
+ suggestion);
.warn("Could not create a Damage Path polygon for Baseline "
+ baseline.name + ". " + suggestion);
return null;
}
Polygon polygon = gf.createPolygon(damagePathBuffer.convexHull()
.getCoordinates());
Coordinate[] damagePathCoords = createTornadoBuffer(validCoords, station, gc,
gf);
Polygon polygon = gf.createPolygon(damagePathCoords);
return polygon;
}
/**
* Creates a buffers a buffer around the storm coordinates. If
* damagePathBuffer is non null, the created buffer will be the union of the
* two buffers.
* Filter the coordinates based on their range to the given radar station.
*
* @param stormCoords
* The storm track coordinates.
* The coordinates.
* @param station
* The station to base distance on.
* @param gf
* The geometry factory.
* @param damagePathBuffer
* The current damage path buffer. May be null.
* @param farCoords
* The list to add any skipped coordinates to.
* @return The created buffer. If damagePathBuffer is not null, the created
* buffer will included damagePathBuffer.
* The radar station.
* @param skippedCoords
* A list where coordinates that are out of range of the station
* will be added to.
* @param validCoords
* A list where coordinates that are in range of the station will
* be added to.
* @param gc
* A GeodeticCalculator.
*/
private static Geometry createBuffer(
StormTrackState.StormCoord[] stormCoords, RadarStation station,
GeometryFactory gf, Geometry damagePathBuffer,
List<StormCoord> farCoords) {
if (stormCoords == null || stormCoords.length == 0) {
return damagePathBuffer;
}
private static void filterCoords(Coordinate[] stormCoords,
RadarStation station, List<Coordinate> skippedCoords,
List<Coordinate> validCoords, GeodeticCalculator gc) {
Coordinate stormCoord;
double distance;
if (stormCoords != null) {
for (int i = 0; i < stormCoords.length; i++) {
stormCoord = stormCoords[i];
gc.setStartingGeographicPoint(stormCoord.x, stormCoord.y);
gc.setDestinationGeographicPoint(station.getLon(),
station.getLat());
distance = gc.getOrthodromicDistance();
GeodeticCalculator gc = new GeodeticCalculator();
Point point;
Geometry buffer;
double distanceMeters; // distance in meters
double distance; // distance in the desired unit
if (distance > MAX_DISTANCE) {
skippedCoords.add(stormCoords[i]);
} else {
validCoords.add(stormCoords[i]);
}
}
}
}
/**
* Creates a buffer around the line defined by the storm coordinates using
* Doug Speheger's tornado damage path algorithm.
*
* @param stormCoords
* The storm coordinates to create a damage path around.
* @param station
* The radar station to use.
* @param gc
* A GeodeticCalculator.
* @param gf
* A GeometryFactory.
* @return A Geometry representing an estimated Tornado Damage Path for the
* given storm coordinates. If the no coordinates are provided, null
* is returned.
*/
private static Coordinate[] createTornadoBuffer(List<Coordinate> stormCoords,
RadarStation station, GeodeticCalculator gc, GeometryFactory gf) {
// left hand side points
List<Point2D> lhsPoints = new ArrayList<>();
// right hand side points
Deque<Point2D> rhsPoints = new ArrayDeque<>();
double uncertainty;
Coordinate stormCoord;
for (int i = 0; i < stormCoords.length; i++) {
stormCoord = stormCoords[i].coord;
gc.setStartingGeographicPoint(stormCoord.x, stormCoord.y);
gc.setDestinationGeographicPoint(station.getLon(), station.getLat());
distanceMeters = gc.getOrthodromicDistance();
distance = METERS_TO.convert(distanceMeters);
/* Create a concave hull for a linear set of coordinates. */
for (int i = 0; i < stormCoords.size(); i++) {
stormCoord = stormCoords.get(i);
uncertainty = calculateUncertainty(station, gc, stormCoord);
if (distance > MAX_DISTANCE) {
farCoords.add(stormCoords[i]);
continue;
if (stormCoords.size() == 1) {
/*
* In the case that there's only one coordinate, draw a circle
* around the point and break out.
*/
for (double d = -180; d < 180; d += END_DEGREE_DIFF) {
gc.setDirection(d, uncertainty);
lhsPoints.add(gc.getDestinationGeographicPoint());
}
break;
}
/*
* Based off of research done by Doug Speheger comparing surveyed
* tornado paths to manually identified radar tornadic vortex
* signatures in 2008-2012. In the initial dataset, 87% of tornadoes
* were within this range of uncertainty.
*/
if (distance < 40.0) {
uncertainty = 0.3 + distance * 0.005;
} else if (distance < 80.0) {
uncertainty = 0.1 + distance * 0.01;
if (i == 0) {
createStartCap(stormCoords, gc, lhsPoints, uncertainty, i);
} else if (i < stormCoords.size() - 1) {
bufferInnerPoint(stormCoord, stormCoords, gc, lhsPoints,
rhsPoints, uncertainty, i, station);
} else {
uncertainty = distance * 0.015 - 0.3;
createEndCap(stormCoords, gc, rhsPoints, uncertainty, i);
}
point = gf.createPoint(stormCoord);
buffer = point.buffer(uncertainty);
if (damagePathBuffer == null) {
damagePathBuffer = buffer;
} else {
damagePathBuffer = damagePathBuffer.union(buffer);
}
}
return damagePathBuffer;
lhsPoints.addAll(rhsPoints);
Coordinate[] coordinates = new Coordinate[lhsPoints.size() + 1];
Point2D point;
for (int i = 0; i < lhsPoints.size(); i++) {
point = lhsPoints.get(i);
coordinates[i] = new Coordinate(point.getX(), point.getY());
}
coordinates[coordinates.length - 1] = coordinates[0];
return coordinates;
}
/**
* Based off of research done by Doug Speheger comparing surveyed tornado
* paths to manually identified radar tornadic vortex signatures in
* 2008-2012. In the initial dataset, 87% of tornadoes were within this
* range of uncertainty.
*
* Note: All units are in meters. Constants have been pre-converted from
* miles to meters.
*
* @param station
* @param gc
* @param coord
* @return
*/
private static double calculateUncertainty(RadarStation station,
GeodeticCalculator gc, Coordinate coord) {
gc.setStartingGeographicPoint(coord.x, coord.y);
gc.setDestinationGeographicPoint(station.getLon(), station.getLat());
double distance = gc.getOrthodromicDistance();
double uncertainty;
if (distance < FORTY_MILES) {
uncertainty = THREE_TENTHS_MILE + distance * 0.005;
} else if (distance < EIGHTY_MILES) {
uncertainty = ONE_TENTH_MILE + distance * 0.01;
} else {
uncertainty = distance * 0.015 - THREE_TENTHS_MILE;
}
return uncertainty;
}
/**
* Creates a buffer around a non-end point. If the path is on a generally
* straight path, just create two points on opposite sides of the path
* point. If the path coordinate is the vertex of an angle is sharp, create
* a couple points around the outside of the angle and create a single point
* on the inside that's uncertainty-meters from the point and both lines
* creating the angle.
*
* @param stormCoord
* @param stormCoords
* @param gc
* @param lhsPoints
* @param rhsPoints
* @param uncertainty
* @param i
* @param station
*/
private static void bufferInnerPoint(Coordinate stormCoord,
List<Coordinate> stormCoords, GeodeticCalculator gc,
List<Point2D> lhsPoints, Deque<Point2D> rhsPoints,
double uncertainty, int i, RadarStation station) {
gc.setStartingGeographicPoint(stormCoord.x, stormCoord.y);
Coordinate nextCoord = stormCoords.get(i + 1);
gc.setDestinationGeographicPoint(nextCoord.x, nextCoord.y);
double azimuthToNext = nonNegativeAzimuth(gc.getAzimuth());
Coordinate prevCoord = stormCoords.get(i - 1);
gc.setDestinationGeographicPoint(prevCoord.x, prevCoord.y);
double azimuthToPrev = nonNegativeAzimuth(gc.getAzimuth());
double angle = Math.abs(azimuthToPrev - azimuthToNext);
boolean sharpAngle = (angle <= SHARP_ANGLE && angle > 0)
|| (angle >= SHARP_ANGLE_INV && angle < 360);
if (sharpAngle) {
boolean rhsOnInside = angle <= SHARP_ANGLE ? azimuthToNext < azimuthToPrev
: azimuthToPrev < azimuthToNext;
double bisectionAngle = Math
.toRadians(angle >= SHARP_ANGLE_INV ? (360.0 - angle) / 2
: angle / 2);
gc.setDirection(geodeticAzimuth(azimuthToNext + 180), uncertainty);
if (rhsOnInside) {
lhsPoints.add(gc.getDestinationGeographicPoint());
createOpposingPoints(stormCoord, gc, lhsPoints,
new ArrayDeque<Point2D>(), uncertainty, azimuthToNext,
azimuthToPrev);
double innerUncertainty = Math.abs(uncertainty
/ Math.sin(bisectionAngle));
if (innerUncertainty < uncertainty) {
innerUncertainty = uncertainty;
}
createOpposingPoints(stormCoord, gc, new ArrayList<Point2D>(),
rhsPoints, innerUncertainty, azimuthToNext,
azimuthToPrev);
gc.setDirection(geodeticAzimuth(azimuthToPrev + 180),
uncertainty);
lhsPoints.add(gc.getDestinationGeographicPoint());
} else {
rhsPoints.push(gc.getDestinationGeographicPoint());
createOpposingPoints(stormCoord, gc, new ArrayList<Point2D>(),
rhsPoints, uncertainty, azimuthToNext, azimuthToPrev);
double innerUncertainty = Math.abs(uncertainty
/ Math.sin(bisectionAngle));
if (innerUncertainty < uncertainty) {
innerUncertainty = uncertainty;
}
createOpposingPoints(stormCoord, gc, lhsPoints,
new ArrayDeque<Point2D>(), innerUncertainty,
azimuthToNext, azimuthToPrev);
gc.setDirection(geodeticAzimuth(azimuthToPrev + 180),
uncertainty);
rhsPoints.push(gc.getDestinationGeographicPoint());
}
} else {
createOpposingPoints(stormCoord, gc, lhsPoints, rhsPoints, uncertainty,
azimuthToNext, azimuthToPrev);
}
}
/**
* Create two points at 180 degrees from each other on the imaginary line
* that bisects the angle created at this point.
*
* @param coord
* @param gc
* @param lhsPoints
* @param rhsPoints
* @param uncertainty
* @param azimuthToNext
* @param azimuthToPrev
*/
private static void createOpposingPoints(Coordinate coord,
GeodeticCalculator gc,
List<Point2D> lhsPoints, Deque<Point2D> rhsPoints,
double uncertainty, double azimuthToNext, double azimuthToPrev) {
gc.setStartingGeographicPoint(coord.x, coord.y);
double pointAzimuth = geodeticAzimuth(Math.min(azimuthToNext,
azimuthToPrev)
+ Math.abs(azimuthToPrev - azimuthToNext) / 2);
if (azimuthToNext <= azimuthToPrev) {
pointAzimuth = geodeticAzimuth(pointAzimuth + 180);
}
gc.setDirection(pointAzimuth, uncertainty);
lhsPoints.add(gc.getDestinationGeographicPoint());
pointAzimuth = geodeticAzimuth(pointAzimuth + 180);
gc.setDirection(pointAzimuth, uncertainty);
rhsPoints.push(gc.getDestinationGeographicPoint());
}
/**
* Create's a curved half-circle buffer around the starting coordinate.
*
* @param stormCoords
* @param gc
* @param lhsPoints
* @param uncertainty
* @param i
*/
private static void createStartCap(List<Coordinate> stormCoords,
GeodeticCalculator gc, List<Point2D> lhsPoints, double uncertainty,
int i) {
Coordinate nextCoord = stormCoords.get(i + 1);
gc.setDestinationGeographicPoint(nextCoord.x, nextCoord.y);
double azimuthToNext = gc.getAzimuth();
double pointAzimuth = geodeticAzimuth(azimuthToNext + 90);
gc.setDirection(pointAzimuth, uncertainty);
lhsPoints.add(gc.getDestinationGeographicPoint());
for (double d = END_DEGREE_DIFF; d <= 180; d += END_DEGREE_DIFF) {
pointAzimuth = geodeticAzimuth(pointAzimuth + END_DEGREE_DIFF);
gc.setDirection(pointAzimuth, uncertainty);
lhsPoints.add(gc.getDestinationGeographicPoint());
}
}
/**
* Create's a curved half-circle buffer around the ending coordinate.
*
* @param stormCoords
* @param gc
* @param rhsPoints
* @param uncertainty
* @param i
*/
private static void createEndCap(List<Coordinate> stormCoords,
GeodeticCalculator gc, Deque<Point2D> rhsPoints,
double uncertainty, int i) {
Coordinate prevCoord = stormCoords.get(i - 1);
gc.setDestinationGeographicPoint(prevCoord.x, prevCoord.y);
double azimuthToPrev = gc.getAzimuth();
double pointAzimuth = geodeticAzimuth(azimuthToPrev - 90);
gc.setDirection(pointAzimuth, uncertainty);
rhsPoints.push(gc.getDestinationGeographicPoint());
for (double d = END_DEGREE_DIFF; d <= 180; d += END_DEGREE_DIFF) {
pointAzimuth = geodeticAzimuth(pointAzimuth - END_DEGREE_DIFF);
gc.setDirection(pointAzimuth, uncertainty);
rhsPoints.push(gc.getDestinationGeographicPoint());
}
}
/**
* Clamps the azimuth to [-180, 180] for use with the GeodeticCalculator.
*
* @param azimuth
* The azimuth.
* @return An equivalent azimuth in [-180, 180].
*/
private static double geodeticAzimuth(double azimuth) {
double az = azimuth;
while (az < -180.0) {
az += 360.0;
}
while (az > 180.0) {
az -= 360.0;
}
return az;
}
/**
* Clamps the azimuth to [0, 360] to simplify the azimath.
*
* @param azimuth
* The azimuth.
* @return An equivalent azimuth in [0, 360].
*/
private static double nonNegativeAzimuth(double azimuth) {
double az = azimuth;
while (az < 0) {
az += 360.0;
}
while (az > 360.0) {
az -= 360.0;
}
return az;
}
}

View file

@ -1,118 +0,0 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.damagepath;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
import com.raytheon.viz.awipstools.ui.layer.DistanceSpeedLayer;
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
import com.vividsolutions.jts.geom.Polygon;
/**
* Action to create a damage path from a DistanceSpeedLayer.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 23, 2015 3977 nabowle Initial creation
* Jun 01, 2015 3975 dgilling Update for DamageLayer changes for
* multiple polygon support.
* Jun 18, 2015 4354 dgilling Update isEnabled to consider editable
* capability.
*
* </pre>
*
* @author nabowle
* @version 1.0
*/
public class ImportFromDistanceSpeedAction extends AbstractRightClickAction {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(ImportFromDistanceSpeedAction.class);
public ImportFromDistanceSpeedAction() {
super("New from Distance Speed Tool");
}
@Override
public void run() {
VizApp.runSync(new Runnable() {
@Override
public void run() {
DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
DistanceSpeedLayer dsLayer = findImportLayer(layer);
// The Distance Speed tool has not been loaded.
if (dsLayer == null) {
return;
}
Polygon polygon = DamagePathUtils.estimateDamagePath(dsLayer);
if (polygon != null) {
layer.addPolygon(polygon.getExteriorRing().getCoordinates());
}
}
});
}
/**
* Returns true iff super.isEnabled() is true and the DistanceSpeed tool is
* loaded, false otherwise.
*/
@Override
public boolean isEnabled() {
AbstractVizResource<?, ?> rsc = getSelectedRsc();
boolean enabled = rsc.getCapability(EditableCapability.class)
.isEditable();
if (enabled) {
if (rsc != null) {
enabled = findImportLayer(rsc) != null;
}
}
return enabled;
}
/**
* Finds the DistanceSpeedLayer.
*
* @param rsc
* The current resource
* @return The found DistanceSpeedLayer, or null if the tool is not loaded.
*/
private DistanceSpeedLayer findImportLayer(AbstractVizResource<?, ?> rsc) {
ResourceList resources = rsc.getDescriptor().getResourceList();
for (ResourcePair rp : resources) {
if (rp.getResource() instanceof DistanceSpeedLayer) {
return (DistanceSpeedLayer) rp.getResource();
}
}
return null;
}
}

View file

@ -0,0 +1,220 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.viz.damagepath;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.drawables.ResourcePair;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.ResourceList;
import com.raytheon.uf.viz.core.rsc.capabilities.EditableCapability;
import com.raytheon.viz.awipstools.ui.layer.InteractiveBaselinesLayer;
import com.raytheon.viz.awipstools.ui.layer.InteractiveBaselinesLayer.Baseline;
import com.raytheon.viz.ui.cmenu.AbstractRightClickAction;
import com.vividsolutions.jts.geom.Polygon;
/**
* Action to create a tornado damage path from an InteractiveBaselineLayer.
*
* Adds a menu item to the DamagePath's legend right-click menu which has a
* submenu to select one of the available baselines.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 23, 2015 3977 nabowle Initial creation
* Jun 01, 2015 3975 dgilling Update for DamageLayer changes for
* multiple polygon support.
* Jun 18, 2015 4354 dgilling Update isEnabled to consider editable
* capability.
* Jun 19, 2015 3977 nabowle Specify Tornado Path.
* Jun 23, 2015 3977 nabowle Switch to InteractiveBaselineLayer.
* Renamed from ImportFromDistanceSpeedAction.
* </pre>
*
* @author nabowle
* @version 1.0
*/
public class NewTornadoDamagePathAction extends AbstractRightClickAction
implements IMenuCreator {
protected static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(NewTornadoDamagePathAction.class);
private Menu menu;
public NewTornadoDamagePathAction() {
super("New Tornado Path from Baseline", SWT.DROP_DOWN);
}
@Override
public Menu getMenu(Control parent) {
if (menu != null) {
menu.dispose();
}
menu = new Menu(parent);
createMenu(menu);
return menu;
}
@Override
public void dispose() {
if (menu != null) {
menu.dispose();
}
}
@Override
public Menu getMenu(Menu parent) {
if (menu != null) {
menu.dispose();
}
createMenu(parent);
return menu;
}
@Override
public IMenuCreator getMenuCreator() {
return this;
}
/**
* Creates a submenu with every displayed baseline, listed in alphabetical
* order.
*
* @param parent
*/
private void createMenu(Menu parent) {
menu = new Menu(parent);
InteractiveBaselinesLayer ibl = findImportLayer(getSelectedRsc());
if (ibl == null || ibl.getCurrentBaselines() == null) {
return;
}
List<Baseline> baselines = new ArrayList<>(Arrays.asList(ibl
.getCurrentBaselines()));
Collections.sort(baselines, new Comparator<Baseline>() {
@Override
public int compare(Baseline b1, Baseline b2) {
return b1.name.compareTo(b2.name);
}
});
for (Baseline baseline : baselines) {
ActionContributionItem aci = new ActionContributionItem(
new ImportFromBaselineInternalAction(baseline));
aci.fill(menu, -1);
}
}
@Override
public boolean isEnabled() {
AbstractVizResource<?, ?> rsc = getSelectedRsc();
boolean enabled = rsc.getCapability(EditableCapability.class)
.isEditable();
if (enabled) {
if (rsc != null) {
enabled = findImportLayer(rsc) != null;
}
}
return enabled;
}
/**
* Finds the import layer.
*
* @param rsc
* The current resource
* @return The found import layer, or null if the tool is not loaded.
*/
private InteractiveBaselinesLayer findImportLayer(
AbstractVizResource<?, ?> rsc) {
ResourceList resources = rsc.getDescriptor().getResourceList();
for (ResourcePair rp : resources) {
if (rp.getResource() instanceof InteractiveBaselinesLayer) {
return (InteractiveBaselinesLayer) rp.getResource();
}
}
return null;
}
/**
* Submenu actions for each available baseline.
*
* Each action is created with one of the available baselines, which when
* run will generate a Tornado damage path for that baseline.
*/
private class ImportFromBaselineInternalAction extends Action {
final Baseline baseline;
public ImportFromBaselineInternalAction(Baseline line) {
super(line.name, Action.AS_PUSH_BUTTON);
this.baseline = line;
}
@Override
public void run() {
VizApp.runSync(new Runnable() {
@Override
public void run() {
DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
Polygon polygon = DamagePathUtils
.estimateTornadoDamagePath(baseline);
if (polygon != null) {
layer.addPolygon(polygon.getExteriorRing()
.getCoordinates());
}
}
});
getContainer().refresh();
}
@Override
public String getText() {
return baseline.name;
}
}
}

View file

@ -41,6 +41,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* Jun 09, 2015 #4355 dgilling Rename action for UI.
* Jun 18, 2015 #4354 dgilling Allow individual properties object for
* each polygon.
* Jun 30, 2015 #4354 dgilling Fix NullPointerException.
*
* </pre>
*
@ -65,7 +66,6 @@ public class OpenGeoJsonPropertiesDlgAction extends AbstractRightClickAction {
Shell shell = VizWorkbenchManager.getInstance()
.getCurrentWindow().getShell();
final DamagePathLayer<?> layer = (DamagePathLayer<?>) getSelectedRsc();
final Map<String, String> geoJsonProps = damagePath
.getProperties();
EditGeoJsonPropertiesDlg dlg = new EditGeoJsonPropertiesDlg(
@ -78,7 +78,6 @@ public class OpenGeoJsonPropertiesDlgAction extends AbstractRightClickAction {
&& (!geoJsonProps.equals(returnValue))) {
Map<String, String> updatedProperties = (Map<String, String>) returnValue;
damagePath.setProperties(updatedProperties);
layer.scheduleSaveJob();
}
}
});

View file

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.
U.S._EXPORT_CONTROLLED_TECHNICAL_DATA
This_software_product_contains_export-restricted_data_whose
export/transfer/disclosure_is_restricted_by_U.S._law._Dissemination
to_non-U.S._persons_whether_in_the_United_States_or_abroad_requires
an_export_license_or_other_authorization.
Contractor_Name:________Raytheon_Company
Contractor_Address:_____6825_Pine_Street,_Suite_340
________________________Mail_Stop_B8
________________________Omaha,_NE_68106
________________________402.291.0100
See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for
further_licensing_information.
-->
<DerivedParameter abbreviation="DIRC" name="Current Direction"
unit="°"
>
<Method name="Direction">
<Field abbreviation="UOGRD" />
<Field abbreviation="VOGRD" />
</Method>
<Method name="Direction">
<Field abbreviation="OGRD" />
</Method>
</DerivedParameter>

View file

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.
U.S._EXPORT_CONTROLLED_TECHNICAL_DATA
This_software_product_contains_export-restricted_data_whose
export/transfer/disclosure_is_restricted_by_U.S._law._Dissemination
to_non-U.S._persons_whether_in_the_United_States_or_abroad_requires
an_export_license_or_other_authorization.
Contractor_Name:________Raytheon_Company
Contractor_Address:_____6825_Pine_Street,_Suite_340
________________________Mail_Stop_B8
________________________Omaha,_NE_68106
________________________402.291.0100
See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for
further_licensing_information.
-->
<DerivedParameter unit="" name="Max 1hr Lightning Threat (flashes/km^2)" abbreviation="LTNG">
<Method name="Alias">
<Field abbreviation="LTNG1hr"/>
</Method>
</DerivedParameter>

View file

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
This_software_was_developed_and_/_or_modified_by_Raytheon_Company,
pursuant_to_Contract_DG133W-05-CQ-1067_with_the_US_Government.
U.S._EXPORT_CONTROLLED_TECHNICAL_DATA
This_software_product_contains_export-restricted_data_whose
export/transfer/disclosure_is_restricted_by_U.S._law._Dissemination
to_non-U.S._persons_whether_in_the_United_States_or_abroad_requires
an_export_license_or_other_authorization.
Contractor_Name:________Raytheon_Company
Contractor_Address:_____6825_Pine_Street,_Suite_340
________________________Mail_Stop_B8
________________________Omaha,_NE_68106
________________________402.291.0100
See_the_AWIPS_II_Master_Rights_File_("Master_Rights_File.pdf")_for
further_licensing_information.
-->
<DerivedParameter abbreviation="MXDVV" name="Max 1hr Downdraft Vertical Velocity" unit="m/s" >
<Method name="Alias">
<Field abbreviation="MAXDVV1hr"/>
</Method>
</DerivedParameter>

Some files were not shown because too many files have changed in this diff Show more