diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..899de31 --- /dev/null +++ b/.classpath @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore index bdf4b0d..9e3e952 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /backup /Belegscanner +/bin/ +/target/ diff --git a/.project b/.project new file mode 100644 index 0000000..d57b672 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + BelegScanner + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b5490a0 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/Belegscanner.ico b/Belegscanner.ico deleted file mode 100644 index 0341321..0000000 Binary files a/Belegscanner.ico and /dev/null differ diff --git a/Belegscanner.lpi b/Belegscanner.lpi deleted file mode 100644 index 1e5ac32..0000000 --- a/Belegscanner.lpi +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - <ResourceType Value="res"/> - <UseXPManifest Value="True"/> - <Icon Value="0"/> - </General> - <BuildModes Count="1"> - <Item1 Name="Default" Default="True"/> - </BuildModes> - <PublishOptions> - <Version Value="2"/> - </PublishOptions> - <RunParams> - <FormatVersion Value="2"/> - <Modes Count="1"> - <Mode0 Name="default"/> - </Modes> - </RunParams> - <RequiredPackages Count="1"> - <Item1> - <PackageName Value="LCL"/> - </Item1> - </RequiredPackages> - <Units Count="2"> - <Unit0> - <Filename Value="Belegscanner.lpr"/> - <IsPartOfProject Value="True"/> - </Unit0> - <Unit1> - <Filename Value="scanner.pas"/> - <IsPartOfProject Value="True"/> - <ComponentName Value="ScanForm"/> - <HasResources Value="True"/> - <ResourceBaseClass Value="Form"/> - </Unit1> - </Units> - </ProjectOptions> - <CompilerOptions> - <Version Value="11"/> - <Target> - <Filename Value="Belegscanner"/> - </Target> - <SearchPaths> - <IncludeFiles Value="$(ProjOutDir)"/> - <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/> - </SearchPaths> - <Linking> - <Options> - <Win32> - <GraphicApplication Value="True"/> - </Win32> - </Options> - </Linking> - </CompilerOptions> - <Debugging> - <Exceptions Count="3"> - <Item1> - <Name Value="EAbort"/> - </Item1> - <Item2> - <Name Value="ECodetoolError"/> - </Item2> - <Item3> - <Name Value="EFOpenError"/> - </Item3> - </Exceptions> - </Debugging> -</CONFIG> diff --git a/Belegscanner.lpr b/Belegscanner.lpr deleted file mode 100644 index 530df48..0000000 --- a/Belegscanner.lpr +++ /dev/null @@ -1,21 +0,0 @@ -program Belegscanner; - -{$mode objfpc}{$H+} - -uses - {$IFDEF UNIX} - cthreads, - {$ENDIF} - Interfaces, // this includes the LCL widgetset - Forms, scanner - { you can add units after this }; - -{$R *.res} - -begin - RequireDerivedFormResource:=True; - Application.Initialize; - Application.CreateForm(TScanForm, ScanForm); - Application.Run; -end. - diff --git a/Belegscanner.lps b/Belegscanner.lps deleted file mode 100644 index bda7fa5..0000000 --- a/Belegscanner.lps +++ /dev/null @@ -1,260 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<CONFIG> - <ProjectSession> - <Version Value="11"/> - <BuildModes Active="Default"/> - <Units Count="16"> - <Unit0> - <Filename Value="Belegscanner.lpr"/> - <IsPartOfProject Value="True"/> - <EditorIndex Value="-1"/> - <CursorPos X="17" Y="10"/> - <UsageCount Value="36"/> - </Unit0> - <Unit1> - <Filename Value="scanner.pas"/> - <IsPartOfProject Value="True"/> - <ComponentName Value="ScanForm"/> - <HasResources Value="True"/> - <ResourceBaseClass Value="Form"/> - <IsVisibleTab Value="True"/> - <TopLine Value="374"/> - <CursorPos X="45" Y="377"/> - <UsageCount Value="36"/> - <Loaded Value="True"/> - <LoadedDesigner Value="True"/> - </Unit1> - <Unit2> - <Filename Value="/usr/share/fpcsrc/3.0.4/rtl/objpas/sysutils/syshelph.inc"/> - <EditorIndex Value="-1"/> - <TopLine Value="111"/> - <CursorPos X="14" Y="151"/> - <UsageCount Value="10"/> - </Unit2> - <Unit3> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/extdlgs.pas"/> - <UnitName Value="ExtDlgs"/> - <EditorIndex Value="-1"/> - <TopLine Value="175"/> - <CursorPos X="29" Y="215"/> - <UsageCount Value="9"/> - </Unit3> - <Unit4> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/stdctrls.pp"/> - <UnitName Value="StdCtrls"/> - <EditorIndex Value="-1"/> - <TopLine Value="389"/> - <CursorPos X="14" Y="437"/> - <UsageCount Value="9"/> - </Unit4> - <Unit5> - <Filename Value="/usr/share/fpcsrc/3.0.4/packages/fcl-process/src/process.pp"/> - <EditorIndex Value="-1"/> - <TopLine Value="99"/> - <CursorPos X="14" Y="131"/> - <UsageCount Value="10"/> - </Unit5> - <Unit6> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/interfaces/gtk2/gtk2int.pas"/> - <UnitName Value="Gtk2Int"/> - <EditorIndex Value="-1"/> - <TopLine Value="811"/> - <CursorPos Y="852"/> - <UsageCount Value="9"/> - </Unit6> - <Unit7> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/graphics.pp"/> - <UnitName Value="Graphics"/> - <EditorIndex Value="-1"/> - <TopLine Value="1426"/> - <CursorPos X="15" Y="1478"/> - <UsageCount Value="10"/> - </Unit7> - <Unit8> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/include/fpimagebitmap.inc"/> - <EditorIndex Value="-1"/> - <TopLine Value="100"/> - <CursorPos Y="141"/> - <UsageCount Value="10"/> - </Unit8> - <Unit9> - <Filename Value="/usr/share/fpcsrc/3.0.4/rtl/objpas/classes/classesh.inc"/> - <EditorIndex Value="-1"/> - <TopLine Value="647"/> - <CursorPos X="14" Y="681"/> - <UsageCount Value="10"/> - </Unit9> - <Unit10> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/calendar.pp"/> - <UnitName Value="Calendar"/> - <EditorIndex Value="-1"/> - <TopLine Value="64"/> - <CursorPos X="14" Y="104"/> - <UsageCount Value="10"/> - </Unit10> - <Unit11> - <Filename Value="scanner.lfm"/> - <EditorIndex Value="-1"/> - <CursorPos X="20" Y="22"/> - <UsageCount Value="10"/> - <DefaultSyntaxHighlighter Value="LFM"/> - </Unit11> - <Unit12> - <Filename Value="/usr/share/fpcsrc/3.0.4/rtl/objpas/sysutils/filutilh.inc"/> - <EditorIndex Value="-1"/> - <TopLine Value="110"/> - <CursorPos X="10" Y="155"/> - <UsageCount Value="10"/> - </Unit12> - <Unit13> - <Filename Value="/usr/share/fpcsrc/3.0.4/rtl/unix/unix.pp"/> - <UnitName Value="Unix"/> - <EditorIndex Value="-1"/> - <TopLine Value="58"/> - <CursorPos X="6" Y="98"/> - <UsageCount Value="10"/> - </Unit13> - <Unit14> - <Filename Value="/usr/lib/lazarus/1.8.2/lcl/controls.pp"/> - <UnitName Value="Controls"/> - <EditorIndex Value="-1"/> - <TopLine Value="1663"/> - <CursorPos X="14" Y="1696"/> - <UsageCount Value="10"/> - </Unit14> - <Unit15> - <Filename Value="/usr/lib/lazarus/2.0.6/components/lazutils/laztracer.pas"/> - <UnitName Value="LazTracer"/> - <EditorIndex Value="-1"/> - <CursorPos Y="50"/> - <UsageCount Value="10"/> - </Unit15> - </Units> - <JumpHistory Count="30" HistoryIndex="29"> - <Position1> - <Filename Value="scanner.pas"/> - <Caret Line="207" Column="21" TopLine="173"/> - </Position1> - <Position2> - <Filename Value="scanner.pas"/> - <Caret Line="215" Column="22" TopLine="175"/> - </Position2> - <Position3> - <Filename Value="scanner.pas"/> - <Caret Line="207" Column="82" TopLine="175"/> - </Position3> - <Position4> - <Filename Value="scanner.pas"/> - <Caret Line="62" Column="42" TopLine="29"/> - </Position4> - <Position5> - <Filename Value="scanner.pas"/> - <Caret Line="60" Column="61" TopLine="27"/> - </Position5> - <Position6> - <Filename Value="scanner.pas"/> - <Caret Line="62" Column="42" TopLine="29"/> - </Position6> - <Position7> - <Filename Value="scanner.pas"/> - <Caret Line="432" Column="5" TopLine="364"/> - </Position7> - <Position8> - <Filename Value="scanner.pas"/> - <Caret Line="62" Column="42" TopLine="29"/> - </Position8> - <Position9> - <Filename Value="scanner.pas"/> - <Caret Line="56" Column="40" TopLine="27"/> - </Position9> - <Position10> - <Filename Value="scanner.pas"/> - <Caret Line="62" Column="32" TopLine="29"/> - </Position10> - <Position11> - <Filename Value="scanner.pas"/> - <Caret Line="59" Column="37" TopLine="27"/> - </Position11> - <Position12> - <Filename Value="scanner.pas"/> - <Caret Line="203" Column="45" TopLine="187"/> - </Position12> - <Position13> - <Filename Value="scanner.pas"/> - <Caret Line="62" Column="39" TopLine="19"/> - </Position13> - <Position14> - <Filename Value="scanner.pas"/> - <Caret Line="208" Column="13" TopLine="174"/> - </Position14> - <Position15> - <Filename Value="scanner.pas"/> - <Caret Line="213" Column="13" TopLine="174"/> - </Position15> - <Position16> - <Filename Value="scanner.pas"/> - <Caret Line="206" Column="19" TopLine="176"/> - </Position16> - <Position17> - <Filename Value="scanner.pas"/> - <Caret Line="214" Column="42" TopLine="177"/> - </Position17> - <Position18> - <Filename Value="scanner.pas"/> - <Caret Line="217" Column="93" TopLine="177"/> - </Position18> - <Position19> - <Filename Value="scanner.pas"/> - <Caret Line="219" Column="65" TopLine="183"/> - </Position19> - <Position20> - <Filename Value="scanner.pas"/> - <Caret Line="204" Column="117" TopLine="186"/> - </Position20> - <Position21> - <Filename Value="scanner.pas"/> - <Caret Line="203" Column="117" TopLine="203"/> - </Position21> - <Position22> - <Filename Value="scanner.pas"/> - <Caret Line="204" Column="117" TopLine="204"/> - </Position22> - <Position23> - <Filename Value="scanner.pas"/> - <Caret Line="403" Column="63" TopLine="365"/> - </Position23> - <Position24> - <Filename Value="scanner.pas"/> - <Caret Line="376" Column="32" TopLine="320"/> - </Position24> - <Position25> - <Filename Value="scanner.pas"/> - <Caret Line="382" Column="24" TopLine="320"/> - </Position25> - <Position26> - <Filename Value="scanner.pas"/> - <Caret Line="21" Column="19"/> - </Position26> - <Position27> - <Filename Value="scanner.pas"/> - <Caret Line="100" Column="26" TopLine="34"/> - </Position27> - <Position28> - <Filename Value="scanner.pas"/> - <Caret Line="382" Column="24" TopLine="316"/> - </Position28> - <Position29> - <Filename Value="scanner.pas"/> - <Caret Line="21" Column="19"/> - </Position29> - <Position30> - <Filename Value="scanner.pas"/> - <Caret Line="116" Column="134" TopLine="67"/> - </Position30> - </JumpHistory> - <RunParams> - <FormatVersion Value="2"/> - <Modes Count="0" ActiveMode="default"/> - </RunParams> - </ProjectSession> -</CONFIG> diff --git a/Belegscanner.res b/Belegscanner.res deleted file mode 100644 index f6e8499..0000000 Binary files a/Belegscanner.res and /dev/null differ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..dea8da7 --- /dev/null +++ b/pom.xml @@ -0,0 +1,52 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>BelegScanner</groupId> + <artifactId>BelegScanner</artifactId> + <version>0.0.2</version> + <name>BelegScanner</name> + + <dependencies> + <dependency> + <groupId>de.srsoftware</groupId> + <artifactId>tools</artifactId> + <version>1.1.17</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>de.srsoftware</groupId> + <artifactId>tools.translations</artifactId> + <version>1.1.3</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>de.srsoftware</groupId> + <artifactId>tools.gui.selectcombobox</artifactId> + <version>0.1.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20200518</version> + </dependency> + <dependency> + <groupId>ch.qos.logback</groupId> + <artifactId>logback-classic</artifactId> + <version>1.2.3</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.8.1</version> + <configuration> + <release>11</release> + </configuration> + </plugin> + </plugins> + </build> +</project> \ No newline at end of file diff --git a/scanner.lfm b/scanner.lfm deleted file mode 100644 index 04f4a05..0000000 --- a/scanner.lfm +++ /dev/null @@ -1,226 +0,0 @@ -object ScanForm: TScanForm - Left = 2222 - Height = 880 - Top = 198 - Width = 1188 - Caption = 'Belegscanner' - ClientHeight = 880 - ClientWidth = 1188 - OnCreate = FormCreate - LCLVersion = '2.0.6.0' - object TypeSelector: TComboBox - Left = 904 - Height = 27 - Top = 208 - Width = 276 - Anchors = [akTop, akRight] - Enabled = False - ItemHeight = 0 - OnChange = TypeSelectorChange - OnKeyDown = ComboKey - TabOrder = 1 - Text = 'Herkunft' - end - object Origin: TComboBox - Left = 904 - Height = 27 - Top = 240 - Width = 272 - Anchors = [akTop, akRight] - Enabled = False - ItemHeight = 0 - OnChange = OriginChange - OnKeyDown = ComboKey - TabOrder = 3 - Text = 'Start' - end - object Destination: TComboBox - Left = 904 - Height = 27 - Top = 304 - Width = 272 - Anchors = [akTop, akRight] - Enabled = False - ItemHeight = 0 - OnChange = DestinationChange - OnKeyDown = ComboKey - TabOrder = 5 - Text = 'Ziel' - end - object FolderName: TLabel - Left = 8 - Height = 17 - Top = 842 - Width = 101 - Anchors = [akLeft, akBottom] - Caption = 'Ordnername' - Font.Height = -16 - Font.Name = 'Sans' - ParentColor = False - ParentFont = False - end - object Product: TComboBox - Left = 904 - Height = 27 - Top = 240 - Width = 276 - Anchors = [akTop, akRight] - Enabled = False - ItemHeight = 0 - OnChange = ProductChange - OnKeyDown = ComboKey - TabOrder = 2 - Text = 'Produkt' - Visible = False - end - object ScanButton: TButton - Left = 904 - Height = 49 - Top = 400 - Width = 272 - Anchors = [akTop, akRight] - Caption = 'scannen!' - Enabled = False - OnClick = ScanButtonClick - TabOrder = 8 - end - object Resolution: TComboBox - Left = 904 - Height = 27 - Top = 368 - Width = 72 - Anchors = [akTop, akRight] - ItemHeight = 0 - ItemIndex = 0 - Items.Strings = ( - '150' - '300' - ) - TabOrder = 7 - Text = '150' - end - object DPI: TLabel - Left = 984 - Height = 14 - Top = 376 - Width = 19 - Anchors = [akTop, akRight] - Caption = 'dpi' - ParentColor = False - end - object BaseFolder: TLabel - Left = 8 - Height = 17 - Top = 818 - Width = 89 - Anchors = [akLeft, akBottom] - Caption = 'BaseFolder' - Font.Height = -16 - Font.Name = 'Sans' - ParentColor = False - ParentFont = False - OnClick = BaseFolderClick - end - object Stop: TComboBox - Left = 904 - Height = 27 - Top = 272 - Width = 272 - Anchors = [akTop, akRight] - Enabled = False - ItemHeight = 0 - OnChange = StopChange - OnKeyDown = ComboKey - TabOrder = 4 - Text = 'Zwischenhalt' - end - object Preview: TImage - Left = 8 - Height = 800 - Top = 8 - Width = 880 - Anchors = [akTop, akLeft, akRight, akBottom] - Center = True - Proportional = True - end - object Calendar: TCalendar - Left = 904 - Height = 190 - Top = 8 - Width = 276 - Anchors = [akTop, akRight] - DateTime = 0 - OnChange = CalendarChange - TabOrder = 0 - end - object PicSize: TComboBox - Left = 904 - Height = 27 - Top = 336 - Width = 272 - Anchors = [akTop, akRight] - ItemHeight = 0 - TabOrder = 6 - Text = '209 x 297 mm' - end - object DropButton: TButton - Left = 904 - Height = 32 - Top = 776 - Width = 276 - Anchors = [akRight, akBottom] - Caption = 'Löschen' - Enabled = False - OnClick = DropButtonClick - ParentShowHint = False - ShowHint = True - TabOrder = 9 - end - object Swap: TButton - Left = 1048 - Height = 30 - Top = 368 - Width = 128 - Anchors = [akTop, akRight] - Caption = 'Start/Ziel tauschen' - OnClick = SwapClick - TabOrder = 10 - end - object extButton: TButton - Left = 904 - Height = 49 - Top = 456 - Width = 272 - Anchors = [akTop, akRight] - Caption = 'extern öffnen' - Enabled = False - OnClick = extButtonClick - TabOrder = 11 - end - object dropBtn: TButton - Left = 904 - Height = 49 - Top = 512 - Width = 272 - Anchors = [akTop, akRight] - Caption = 'Datensatz löschen' - OnClick = dropBtnClick - TabOrder = 12 - end - object OpenDir: TButton - Left = 904 - Height = 32 - Top = 744 - Width = 276 - Anchors = [akRight, akBottom] - Caption = 'Ordner öffnen' - OnClick = OpenDirClick - ParentShowHint = False - ShowHint = True - TabOrder = 13 - end - object BaseFolderDialog: TSelectDirectoryDialog - left = 520 - top = 128 - end -end diff --git a/scanner.pas b/scanner.pas deleted file mode 100644 index e22b5ec..0000000 --- a/scanner.pas +++ /dev/null @@ -1,459 +0,0 @@ -unit scanner; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtDlgs, - StdCtrls, ExtCtrls, Calendar, Unix; - -type - - { ScanThread } - ScanThread = class(TThread) - private - dbtn, obtn, sbtn : TButton; - folder,r :String; - s:TPoint; - p:TImage; - protected - procedure Execute; override; - public - constructor Create(scanButton: TButton; dir: String; size: TPoint; resolution: String; preview: TImage; dropButton: TButton; openButton: TButton); - end; - - { TScanForm } - TScanForm = class(TForm) - dropBtn: TButton; - OpenDir: TButton; - extButton: TButton; - Swap: TButton; - DropButton: TButton; - Calendar: TCalendar; - PicSize: TComboBox; - Preview: TImage; - Stop: TComboBox; - DPI: TLabel; - BaseFolder: TLabel; - Resolution: TComboBox; - BaseFolderDialog: TSelectDirectoryDialog; - ScanButton: TButton; - Product: TComboBox; - Destination: TComboBox; - FolderName: TLabel; - Origin: TComboBox; - TypeSelector: TComboBox; - - procedure BaseFolderClick(Sender: TObject); - procedure dropBtnClick(Sender: TObject); - procedure extButtonClick(Sender: TObject); - procedure DropButtonClick(Sender: TObject); - procedure CalendarChange(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure OpenDirClick(Sender: TObject); - procedure ProductChange(Sender: TObject); - procedure DestinationChange(Sender: TObject); - procedure OriginChange(Sender: TObject); - procedure ScanButtonClick(Sender: TObject); - procedure StopChange(Sender: TObject); - procedure SwapClick(Sender: TObject); - procedure TypeSelectorChange(Sender: TObject); - function ExportConfig(): string; - function ExportOptions(dropDown: TComboBox): string; - procedure ComboKey(Sender: TObject; var Key: Word; Shift: TShiftState); - procedure UpdateFolder(); - procedure MixLocations(d1: TComboBox; d2: TComboBox; d3: TComboBox); - procedure DeleteStationFrom(combo: TComboBox; station: string; defaultName : string); - procedure DeleteStation(station : string); - private - date: TDateTime; - function getSize(): TPoint; - - public - const - SCANNING : Integer = 1; - IDLE: Integer = 0; - end; - -var - ScanForm: TScanForm; - -implementation - -{$R *.lfm} - -{ ScanThread } - -constructor ScanThread.Create(scanButton: TButton; dir: String; size: TPoint; resolution: String; preview: TImage; dropButton: TButton; openButton: TButton ); -begin - sbtn := scanButton; - obtn := openButton; - dbtn := dropButton; - folder:=dir; - s:=size; - r:=resolution; - p:=preview; - inherited Create(false); -end; - -procedure ScanThread.Execute; -var - fname: String; - num: Integer; - pic: TPicture; -begin - ForceDirectories(folder); - num := 0; - repeat - num := num +1; - fname := 'scan_'; - if (num<10) then fname:=fname+'0'; - if (num<100) then fname:=fname+'0'; - if (num<1000) then fname:=fname+'0'; - fname := fname+IntToStr(num)+'.jpg'; - until not FileExists(folder+fname); - fpSystem('scanimage -x '+IntToStr(s.x)+' -y '+IntToStr(s.y)+' --mode Color --resolution '+r+' --format jpeg > "'+folder+fname+'"'); - try - pic:=TPicture.Create; - pic.LoadFromFile(folder+fname); - p.Picture:=pic; - p.Hint:=folder+fname; - finally - end; - dbtn.Hint:=folder+fname; - dbtn.Caption:=fname+' löschen'; - dbtn.Enabled:=true; - obtn.Enabled:=true; - sbtn.Enabled:=true; - sbtn.Tag := TScanForm.IDLE; -end; - -function allowed(s: String): boolean; -begin - Result := true; - if (s = '') then Result := false; - if (s = 'Start') then Result := false; - if (s = 'Ziel') then Result := false; - if (s = 'Zwischenhalt') then Result := false; -end; - -procedure TScanForm.MixLocations(d1: TComboBox; d2: TComboBox; d3: TComboBox); -var - list: TStringList; -begin - list := TStringList.Create; - list.Sorted := True; - if (allowed(d1.Text)) then d1.Items.Add(d1.Text); - if (allowed(d2.Text)) then d2.Items.Add(d2.Text); - if (allowed(d3.Text)) then d3.Items.Add(d3.Text); - list.Assign(d1.Items); - list.AddStrings(d2.Items); - list.AddStrings(d3.Items); - d1.Items.Assign(list); - d2.Items.Assign(list); - d3.Items.Assign(list); -end; - -function TScanForm.ExportConfig(): string; -begin - Result := 'folder:'+BaseFolder.Caption+#13; - Result := Result + 'types:' + ExportOptions(TypeSelector) + #13; - Result := Result + 'items:' + ExportOptions(Product) + #13; - MixLocations(Origin, Destination, Stop); - Result := Result + 'locations:' + ExportOptions(Origin) + #13; - Result := Result + 'sizes:' + ExportOptions(PicSize) +#13; -end; - -function TScanForm.ExportOptions(dropDown: TComboBox): string; -var - list: TStringList; - item, current: string; - i: integer; - drop: Boolean; -begin - // make sure the current text appears in future lists - item := dropDown.Text; - drop := item.StartsWith(' '); - - if drop then - begin - i := 0; - while i < dropDown.Items.Count do - begin - item := Trim(item); - current := Trim(dropDown.Items[i]); - if current = item then dropDown.Items.Delete(i) else i := i+1; - end; - end else dropDown.Items.Add(item); - - // create a StringList to sort and concatenate - list := TStringList.Create; - list.StrictDelimiter := True; - list.Sorted := True; - - // put all items in the list, will sort and remove duplicates - list.Assign(dropDown.Items); - - // update dropdown - dropDown.Items.Assign(list); - - // return json array - Result := list.DelimitedText -end; - -procedure TScanForm.ComboKey(Sender: TObject; var Key: Word; Shift: TShiftState); -var - combo : TComboBox; - index : integer; - tx : string; -begin - if key = 40 then - begin - if TObject(Sender) is TComboBox then - begin - combo := TComboBox(Sender); - tx := combo.Text; - for index := 0 to combo.Items.Count-1 do - begin - if combo.Items[index].StartsWith(tx,true) then - begin - combo.ItemIndex:=index-1; - Exit; - end; - end; - end; - end; -end; - -procedure TScanForm.TypeSelectorChange(Sender: TObject); -var - state: boolean; -begin - TypeSelector.Tag := 1; - state := TypeSelector.Text = 'Ticket'; - Origin.Enabled := state; - Origin.Visible := state; - Stop.Enabled := state; - Stop.Visible := state; - Destination.Enabled := state; - Destination.Visible := state; - Swap.Enabled:=state; - Product.Enabled := not state; - Product.Visible := not state; - if (ScanButton.Tag <> TScanForm.SCANNING) then ScanButton.Enabled:=true; - UpdateFolder(); -end; - -procedure TScanForm.CalendarChange(Sender: TObject); -begin - date := Calendar.DateTime; - TypeSelector.Enabled := True; - UpdateFolder(); -end; - -procedure TScanForm.OriginChange(Sender: TObject); -begin - Origin.Tag := 1; - UpdateFolder(); -end; - -function TScanForm.getSize(): TPoint; -var - arr: TStringArray; - s: String; - w, h: Integer; -begin - s:=PicSize.Text; - arr:=s.Split(['x','m']); - w:=StrToInt(arr[0].Trim); - h:=StrToInt(arr[1].Trim); - PicSize.Caption:=IntToStr(w)+' x '+IntToStr(h)+' mm'; - Result := TPoint.Create(w,h); -end; - -procedure TScanForm.ScanButtonClick(Sender: TObject); -var - config: TFileStream; - filename: string; - json: string; - size: TPoint; -begin - ScanButton.Enabled:=false; - ScanButton.Tag:=TScanForm.SCANNING; - filename := GetEnvironmentVariable('HOME') + '/.config/belegscanner.conf'; - size := getSize(); - json := ExportConfig(); - try - config := TFilestream.Create(filename, fmCreate); - config.Write(json[1], json.Length); - finally - config.Free; - end; - ScanThread.Create(ScanButton,BaseFolder.Caption+'/'+FolderName.Caption+'/',size,Resolution.Caption,Preview,DropButton,extButton); -end; - -procedure TScanForm.StopChange(Sender: TObject); -begin - Stop.Tag := 1; - UpdateFolder(); -end; - -procedure TScanForm.SwapClick(Sender: TObject); -var - dummy: String; -begin - dummy:=Origin.Text; - Origin.Text := Destination.Text; - Destination.Text := dummy; - UpdateFolder(); -end; - -procedure TScanForm.DestinationChange(Sender: TObject); -begin - Destination.Tag := 1; - UpdateFolder(); -end; - -procedure TScanForm.ProductChange(Sender: TObject); -begin - Product.Tag := 1; - UpdateFolder(); -end; - - -procedure addItemsTo(combo: TComboBox; line: String); -var - parts: TStringArray; - fixed, part: string; -begin - parts := line.Split(','); - for part in parts do - begin - fixed := part.Replace('"',''); - if (fixed <> '') then combo.Items.Add(fixed); - end; -end; - -procedure TScanForm.FormCreate(Sender: TObject); -var - filename: String; - lines: TStringList; - line: String; - index: integer; -begin - BaseFolder.Caption:=GetEnvironmentVariable('HOME'); - filename := GetEnvironmentVariable('HOME') + '/.config/belegscanner.conf'; - lines := TStringList.Create; - Calendar.DateTime:=Now; - try - lines.LoadFromFile(filename); - for index := 0 to lines.Count-1 do - begin - line:=lines.Strings[index]; - if line.StartsWith('folder:') then - begin - line:=line.Substring(7); - BaseFolder.Caption:=line; - end; - if line.StartsWith('types:') then addItemsTo(TypeSelector,line.Substring(6)); - if line.StartsWith('items:') then addItemsTo(Product,line.Substring(6)); - if line.StartsWith('sizes:') then addItemsTo(PicSize,line.Substring(6)); - if line.StartsWith('locations:') then - begin - line := line.Substring(10); - addItemsTo(Origin,line); - addItemsTo(Destination,line); - addItemsTo(Stop,line); - end; - end - finally - end; -end; - -procedure TScanForm.OpenDirClick(Sender: TObject); -begin - WriteLn(BaseFolder.Caption); - fpSystem('gio open "'+BaseFolder.Caption+'"'); -end; - -procedure TScanForm.BaseFolderClick(Sender: TObject); -begin - BaseFolderDialog.FileName:=BaseFolder.Caption; - BaseFolderDialog.Execute; - BaseFolder.Caption := BaseFolderDialog.FileName; -end; - -procedure TScanForm.DeleteStationFrom(combo: TComboBox; station : string; defaultName : string); -var - index : integer; -begin - index := combo.Items.IndexOf(station); - if index > -1 then - begin - combo.Items.Delete(index); - combo.Text := defaultName; - end; -end; - -procedure TScanForm.DeleteStation(station : string); -begin - DeleteStationFrom(Origin,station,'Start'); - DeleteStationFrom(Stop,station,'Zwischenhalt'); - DeleteStationFrom(Destination,station,'Ziel'); -end; - -procedure TScanForm.dropBtnClick(Sender: TObject); -var - tx : string; -begin - tx := TypeSelector.Text; - if (tx <> 'Herkunft') and (tx <> 'Ticket') then - begin - TypeSelector.Items.Delete(TypeSelector.ItemIndex); - TypeSelector.Text := 'Herkunft'; - end; - - tx := Product.Text; - if Product.Enabled and (tx <> 'Produkt') then - begin - Product.Items.Delete(Product.ItemIndex); - Product.Text := 'Produkt'; - end; - - if Origin.Enabled and (Origin.Text <> 'Start') then deleteStation(Origin.Text); - if Stop.Enabled and (Stop.Text <> 'Zwischenhalt') then deleteStation(Stop.Text); - if Destination.Enabled and (Destination.Text <> 'Ziel') then deleteStation(Destination.Text); -end; - -procedure TScanForm.extButtonClick(Sender: TObject); -var - cmd: string; -begin - cmd := 'gvfs-open "'+DropButton.Hint+'"'; - fpSystem(cmd); -end; - -procedure TScanForm.DropButtonClick(Sender: TObject); -begin - DeleteFile(DropButton.Hint); - Preview.Picture:=nil; - DropButton.Enabled:=false; - extButton.Enabled:=false; -end; - - -procedure TScanForm.UpdateFolder(); -var - tx: string; -begin - tx := FormatDateTime('YYYY-MM-DD', date) + ' - '; - if (Product.Enabled and (Product.Tag > 0) and not( Product.Text = '') and not (Product.Text = 'Produkt')) then tx := tx + Trim(Product.Text) + ' von '; - if (TypeSelector.Tag > 0) then tx := tx + Trim(TypeSelector.Text); - if (Origin.Enabled and (Origin.Tag > 0)) then tx := tx + ': ' + Trim(Origin.Text); - if (Stop.Enabled and (Stop.Tag > 0) and not (Stop.Text = '')and not (Stop.Text = 'Zwischenhalt')) then tx := tx + ' - ' + Trim(Stop.Text); - if (Destination.Enabled and (Destination.Tag > 0)) then tx := tx + ' - ' + Trim(Destination.Text); - FolderName.Caption := tx; -end; - -end. diff --git a/src/main/java/de/srsoftware/belegscanner/Application.java b/src/main/java/de/srsoftware/belegscanner/Application.java new file mode 100644 index 0000000..9181664 --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/Application.java @@ -0,0 +1,14 @@ +package de.srsoftware.belegscanner; + +import java.io.IOException; + +import de.srsoftware.belegscanner.gui.MainFrame; + +public class Application { + + public static void main(String[] args) throws IOException { + Configuration config = new Configuration(Constants.APPLICATION_NAME); + MainFrame app = new MainFrame(config); + app.setDefaultCloseOperation(MainFrame.EXIT_ON_CLOSE); + } +} diff --git a/src/main/java/de/srsoftware/belegscanner/Configuration.java b/src/main/java/de/srsoftware/belegscanner/Configuration.java new file mode 100644 index 0000000..c8a512b --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/Configuration.java @@ -0,0 +1,145 @@ +package de.srsoftware.belegscanner; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Configuration { + + private static final Logger LOG = LoggerFactory.getLogger(Configuration.class); + private File file; + private JSONObject json = new JSONObject(); + + public Configuration(String appName) throws IOException { + String home = System.getProperty("user.home"); + String fileName = new StringBuilder().append(home).append(File.separator).append(".config").append(File.separator).append(appName).append(File.separator).append("config.json").toString(); + file = new File(fileName); + if (file.exists()) { + LOG.info("{} found, loading…",file); + FileReader in = new FileReader(file); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(buffer); + in.transferTo(writer); + writer.close(); + String jsonString = buffer.toString(StandardCharsets.UTF_8); + LOG.debug("Loaded json: {}",jsonString); + json = jsonString.startsWith("{") ? new JSONObject(jsonString) : new JSONObject(); + in.close(); + } else { + LOG.info("{} not found, creating new config.",file); + json = new JSONObject(); + } + } + + private void save() throws IOException { + LOG.debug("Trying to save config…"); + File dir = file.getParentFile(); + if (!dir.exists()) dir.mkdirs(); + FileWriter out = new FileWriter(file); + json.write(out, 2, 0); + out.close(); + } + + public JSONArray getOrCreateArray(String key) { + LOG.debug("requesting {} from config.",key); + String[] parts = key.split("\\."); + JSONObject localJson = json; + boolean update = false; + JSONArray result = null; + for (int i=0; i<parts.length; i++) { + String localKey = parts[i]; + LOG.debug("localKey = {}",localKey); + boolean lastPart = i == parts.length-1; + if (!localJson.has(localKey)) { + LOG.debug("{} not present in {}, creating…",localKey,localJson); + localJson.put(localKey, lastPart ? new JSONArray() : new JSONObject()); + update = true; + } + if (lastPart) { + result = localJson.getJSONArray(localKey); + } else localJson = localJson.getJSONObject(localKey); + } + if (update) try { + save(); + } catch (IOException ex) { + LOG.warn("Was not able to write config to {}!",file); + } + return result; + } + + @SuppressWarnings("unchecked") + public <T> T get(String key) { + LOG.debug("requesting {} from config.",key); + String[] parts = key.split("\\."); + JSONObject localJson = json; + for (int i=0; i<parts.length; i++) { + String localKey = parts[i]; + LOG.debug("localKey = {}",localKey); + boolean lastPart = i == parts.length-1; + if (!localJson.has(localKey)) return null; + if (lastPart) return (T) localJson.get(localKey); + localJson = localJson.getJSONObject(localKey); + } + return null; + } + + @SuppressWarnings("unchecked") + public <T> T getOrCreate(String key, T preset) { + LOG.debug("requesting {} from config.",key); + String[] parts = key.split("\\."); + JSONObject localJson = json; + boolean update = false; + Object result = preset; + for (int i=0; i<parts.length; i++) { + String localKey = parts[i]; + LOG.debug("localKey = {}",localKey); + boolean lastPart = i == parts.length-1; + if (!localJson.has(localKey)) { + LOG.debug("{} not present in {}, creating…",localKey,localJson); + localJson.put(localKey, lastPart ? preset : new JSONObject()); + update = true; + } + if (lastPart) { + result = localJson.get(localKey); + } else localJson = localJson.getJSONObject(localKey); + } + if (update) try { + save(); + } catch (IOException ex) { + LOG.warn("Was not able to write config to {}!",file); + } + return (T) result; + } + + public void set(String key, Object value) { + LOG.debug("setting {} to {}",key,value); + String[] parts = key.split("\\."); + JSONObject localJson = json; + for (int i=0; i<parts.length; i++) { + String localKey = parts[i]; + LOG.debug("localKey = {}",localKey); + boolean lastPart = i == parts.length-1; + if (!localJson.has(localKey)) { + LOG.debug("{} not present in {}, creating…",localKey,localJson); + localJson.put(localKey, lastPart ? value : new JSONObject()); + } + if (lastPart) break; + localJson = localJson.getJSONObject(localKey); + } + LOG.debug("altered json: {}",json); + try { + save(); + } catch (IOException ex) { + LOG.warn("Was not able to write config to {}!",file); + } + } +} diff --git a/src/main/java/de/srsoftware/belegscanner/Constants.java b/src/main/java/de/srsoftware/belegscanner/Constants.java new file mode 100644 index 0000000..807c1e1 --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/Constants.java @@ -0,0 +1,7 @@ +package de.srsoftware.belegscanner; + +public class Constants { + + public static final String APPLICATION_NAME = "BelegScanner"; + +} diff --git a/src/main/java/de/srsoftware/belegscanner/gui/FilterComboBoxText.java b/src/main/java/de/srsoftware/belegscanner/gui/FilterComboBoxText.java new file mode 100644 index 0000000..3ab0ce0 --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/gui/FilterComboBoxText.java @@ -0,0 +1,112 @@ +package de.srsoftware.belegscanner.gui; + +import java.awt.EventQueue; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +public class FilterComboBoxText { + + private JFrame frame; + private final JComboBox<String> comboBox = new JComboBox<>(); + private static List<String>listForComboBox= new ArrayList<String>(); + + /** + * Launch the application. + */ + public static void main(String[] args) { + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + FilterComboBoxText window = new FilterComboBoxText(); + window.frame.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + + listForComboBox.add("Lion"); + listForComboBox.add("LionKing"); + listForComboBox.add("Mufasa"); + listForComboBox.add("Nala"); + listForComboBox.add("KingNala"); + listForComboBox.add("Animals"); + listForComboBox.add("Anims"); + listForComboBox.add("Fish"); + listForComboBox.add("Jelly Fish"); + listForComboBox.add("I am the boss"); + + + } + + public FilterComboBoxText() { + initialize(); + } + + private void initialize() { + frame = new JFrame(); + frame.setBounds(100, 100, 412, 165); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(null); + comboBox.setEditable(true); + + comboBox.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent arg0) { + + } + }); + + for(String detail : listForComboBox) comboBox.addItem(detail); + final JTextField textfield = (JTextField) comboBox.getEditor().getEditorComponent(); + textfield.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent ke) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + if(!textfield.getText().isEmpty()){ + comboBoxFilter(textfield.getText()); + } + } + }); + + } + }); + comboBox.setBounds(10, 39, 364, 29); + frame.getContentPane().add(comboBox); + } + + public void comboBoxFilter(String enteredText) { + System.out.println(comboBox.getItemCount()); + + if (!comboBox.isPopupVisible()) { + comboBox.showPopup(); + } + + List<String> filterArray= new ArrayList<String>(); + for (int i = 0; i < listForComboBox.size(); i++) { + if (listForComboBox.get(i).toLowerCase().contains(enteredText.toLowerCase())) { + filterArray.add(listForComboBox.get(i)); + } + } + if (filterArray.size() > 0) { + DefaultComboBoxModel<String> model = (DefaultComboBoxModel<String>) comboBox.getModel(); + model.removeAllElements(); + model.addElement(""); + for (String s: filterArray) + model.addElement(s); + + JTextField textfield = (JTextField) comboBox.getEditor().getEditorComponent(); + textfield.setText(enteredText); + } + } + +} \ No newline at end of file diff --git a/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java b/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java new file mode 100644 index 0000000..8151f28 --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/gui/MainFrame.java @@ -0,0 +1,118 @@ +package de.srsoftware.belegscanner.gui; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.util.Date; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JFrame; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.srsoftware.belegscanner.Configuration; + + +public class MainFrame extends JFrame { + private static final Logger LOG = LoggerFactory.getLogger(MainFrame.class); + + private static final long serialVersionUID = 210283601541223645L; + + private static final String HOME = System.getProperty("user.home"); + private static final Pattern MARKEN = Pattern.compile("\\$([a-zA-Z]+)"); + + private StatusBar statusBar; + private Toolbar toolbar; + + private HashMap<String,String> fields = new HashMap<>(); + + private String path = ""; + + private String category =""; + + private Date date = new Date(); + + private String patchedPath = ""; + + private Configuration config; + + public MainFrame(Configuration config) { + this.config = config; + int width = config.getOrCreate("app.main.dimenstion.w",800); + int height = config.getOrCreate("app.main.dimenstion.h",600); + + BorderLayout layout = new BorderLayout(); + setLayout(layout); + + toolbar = new Toolbar(config); + statusBar = new StatusBar(); + + add(toolbar,BorderLayout.EAST); + add(statusBar,BorderLayout.SOUTH); + toolbar.addCategoryListener(this::setCategory) + .addDateListener(this::setDate) + .addFieldListener(this::setField) + .addPathListener(this::setPath) + .addScanListener(this::scan); + + setPreferredSize(new Dimension(width,height)); + pack(); + setVisible(true); + } + + private void addFieldsFor(String path) { + Vector<String> marks = new Vector<>(); + Matcher matches = MARKEN.matcher(path); + while (matches.find()) marks.add(matches.group(1)); + toolbar.addFieldsFor(marks); + }; + + private void scan(ActionEvent ev) { + LOG.debug("Scanning into '{}'",patchedPath); + config.set("app.categories."+category+".path",path); + } + + private void setCategory(String category) { + this.category = category; + updatePath(); + + } + + private void setDate(Date date) { + this.date = date; + updatePath(); + } + + private void setField(String key, String val) { + fields.put(key, val); + updatePath(); + } + + + private void setPath(String path) { + this.path = path; + updatePath(); + } + + @SuppressWarnings("deprecation") + private void updatePath() { + LOG.debug("updatePath() [path = {}]",path); + int year = 1900+date.getYear(); + int month = date.getMonth()+1; + int day = date.getDate(); + patchedPath = path.replace("$HOME",HOME) + .replace("$KATEGORIE", category) + .replace("$JAHR", year+"") + .replace("$MONAT", month<10 ? "0"+month : ""+month) + .replace("$TAG", day < 10 ? "0"+day : ""+day); + + addFieldsFor(patchedPath); + for (Entry<String, String> entry : fields.entrySet()) patchedPath = patchedPath.replace("$"+entry.getKey(), entry.getValue()); + statusBar.setPath(patchedPath); + } +} diff --git a/src/main/java/de/srsoftware/belegscanner/gui/StatusBar.java b/src/main/java/de/srsoftware/belegscanner/gui/StatusBar.java new file mode 100644 index 0000000..abee5a0 --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/gui/StatusBar.java @@ -0,0 +1,27 @@ +package de.srsoftware.belegscanner.gui; + +import javax.swing.BoxLayout; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StatusBar extends JPanel { + + private static final Logger LOG = LoggerFactory.getLogger(StatusBar.class); + + private static final long serialVersionUID = 8102800846089594705L; + private JLabel path; + + public StatusBar() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + add(path = new JLabel()); + } + + public StatusBar setPath(String path) { + LOG.debug("setPath({})",path); + this.path.setText(path); + return this; + } +} diff --git a/src/main/java/de/srsoftware/belegscanner/gui/Toolbar.java b/src/main/java/de/srsoftware/belegscanner/gui/Toolbar.java new file mode 100644 index 0000000..388a283 --- /dev/null +++ b/src/main/java/de/srsoftware/belegscanner/gui/Toolbar.java @@ -0,0 +1,195 @@ +package de.srsoftware.belegscanner.gui; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Vector; +import java.util.stream.Collectors; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.srsoftware.belegscanner.Configuration; +import de.srsoftware.tools.gui.DateChooser; +import de.srsoftware.tools.gui.SelectComboBox; + +public class Toolbar extends JPanel { + + private static final Logger LOG = LoggerFactory.getLogger(Toolbar.class); + + public interface CategoryListener{ + public void setCategory(String category); + } + + public interface DateListener{ + public void setDate(Date date); + } + + public interface FieldListener{ + public void setField(String name, String value); + } + + public interface PathListener{ + public void setPath(String path); + } + + + private static final long serialVersionUID = -5834326573752788233L; + + private Vector<Object> categories = new Vector<>(); + private Vector<Object> paths = new Vector<>(); + + private HashSet<CategoryListener> categoryListeners = new HashSet<>(); + private HashSet<DateListener> dateListeners = new HashSet<>(); + private HashSet<FieldListener> fieldListeners = new HashSet<>(); + private HashSet<PathListener> pathListeners = new HashSet<>(); + private HashSet<ActionListener> scanListeners = new HashSet<>(); + private HashMap<String,Component> additonalComponents = new HashMap<>(); + + private DateChooser date; + + private Configuration config; + + private SelectComboBox pathPicker; + + + + public Toolbar(Configuration config) { + this.config = config; + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + add(datePicker()); + add(input("Kategorie",categoryPicker(config))); + add(input("Pfad",pathPicker = pathPicker())); + add(scanButton()); + add(externButton()); + } + + public void addFieldsFor(Vector<String> marks) { + LOG.debug("addFieldsFor({})",marks); + + List<String> deleted = additonalComponents.keySet().stream().filter(key -> !marks.contains(key)).collect(Collectors.toList()); + deleted.forEach(name -> remove(additonalComponents.remove(name))); + + for (String name : marks) { + if (additonalComponents.containsKey(name)) continue; + List<Object> knownValues = List.of(); + SelectComboBox valuePicker = new SelectComboBox(knownValues).onUpdateText(newText -> updateField(name,newText)); + Component input = input(name, valuePicker); + add(input,getComponentCount()-2); + additonalComponents.put(name, input); + } + } + + public Toolbar addCategoryListener(CategoryListener listener) { + categoryListeners.add(listener); + return this; + } + + public Toolbar addDateListener(DateListener listener) { + dateListeners.add(listener); + return this; + } + + public Toolbar addFieldListener(FieldListener listener) { + fieldListeners.add(listener); + return this; + } + + public Toolbar addPathListener(PathListener listener){ + pathListeners.add(listener); + return this; + } + + public Toolbar addScanListener(ActionListener listener) { + scanListeners.add(listener); + return this; + } + + + private Component categoryPicker(Configuration config) { + JSONObject elements = config.getOrCreate("app.categories",new JSONObject()); + elements.keySet().forEach(categories::add); + return new SelectComboBox(categories).onUpdateText(this::updateCat); + } + + private Component datePicker() { + date = new DateChooser(); + Dimension dim = new Dimension(400, 250); + date.setMaximumSize(dim); + date.addActionListener(ev -> dateListeners.forEach(listener -> listener.setDate(date.getSelectedDate()))); + return date; + } + + private JButton externButton() { + JButton btn = new JButton("extern öffnen"); + return btn; + } + + private Component input(String caption, Component component) { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS)); + panel.add(new JLabel(caption+" ")); + panel.add(component); + return panel; + } + + + public Date getDate() { + return date.getSelectedDate(); + } + + private SelectComboBox pathPicker() { + JSONObject cats = config.getOrCreate("app.categories",new JSONObject()); + for (String catName : cats.keySet()) { + JSONObject catInfo = cats.getJSONObject(catName); + if (catInfo.has("path")) paths.add(catInfo.get("path")); + } + paths.add("$HOME/$JAHR/$MONAT-$TAG - $KATEGORIE"); + return new SelectComboBox(paths).onUpdateText(this::updatePath); + } + + private Component scanButton() { + JButton scanButton = new JButton("scannen!"); + scanButton.addActionListener(this::scanPressed); + return scanButton; + } + + private void scanPressed(ActionEvent evt) { + scanListeners.forEach(l->l.actionPerformed(evt)); + } + + protected void updateCat(String newCat) { + LOG.debug("updateCat({})",newCat); + categoryListeners.forEach(l -> l.setCategory(newCat)); + if (!newCat.isEmpty()) { + String path = config.get("app.categories."+newCat+".path"); + LOG.debug("path: {}",path); + if (path != null) { + pathPicker.setSelectedItem(path); + updatePath(path); + } + } + } + + private void updateField(String name, String val) { + LOG.debug("updateField({},{})",name,val); + fieldListeners.forEach(l -> l.setField(name,val)); + } + + + protected void updatePath(String newPath) { + LOG.debug("updatePath({})",newPath); + pathListeners.forEach(l -> l.setPath(newPath)); + } +}