diff --git a/.gitignore b/.gitignore index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..688ab371e136df9ae499152e22881846c1d254ea 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,23 @@ +# project documentation +/doc/projectDocumentation/Medien +/doc/projectDocumentation/*.aux +/doc/projectDocumentation/*.bbl +/doc/projectDocumentation/*.bib +/doc/projectDocumentation/*.blg +/doc/projectDocumentation/*.gz +/doc/projectDocumentation/*.lof +/doc/projectDocumentation/*.log +/doc/projectDocumentation/*.lol +/doc/projectDocumentation/*.lot +/doc/projectDocumentation/*.out +/doc/projectDocumentation/*.run* +/doc/projectDocumentation/*.toc + +# libraries Arduino +/src/lightControlUnit/libraries + +# vsCode +/.vscode + +# eclips +*.project \ No newline at end of file diff --git a/README.md b/README.md index ba5522153247ada4da9154711716e3f7fbce21a8..0c5661dc7825ea979fcd049b3dddd34424eb7661 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,11 @@ KIWI is a light control system for DMX-fixtures in a home environment. ## Features +With this software, you can controlle DMX fixture via Art-Net ## Project status -Work in progress +Sofwtare: DONE +Documentation: WORK IN PROGRESS ## Author Sebastian Böttger diff --git a/doc/codeDocumentation/diagrams/classDiagramLightControlSoftware.uxf b/doc/codeDocumentation/diagrams/classDiagramLightControlSoftware.uxf new file mode 100644 index 0000000000000000000000000000000000000000..6b2b1bdff03a43f968bc27756157006617a137f6 --- /dev/null +++ b/doc/codeDocumentation/diagrams/classDiagramLightControlSoftware.uxf @@ -0,0 +1,34 @@ +<diagram program="umletino" version="15.1"><zoom_level>13</zoom_level><element><id>UMLClass</id><coordinates><x>13</x><y>377</y><w>130</w><h>39</h></coordinates><panel_attributes>Fixture</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>0</x><y>260</y><w>169</w><h>39</h></coordinates><panel_attributes>FixturesRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>247</x><y>260</y><w>169</w><h>39</h></coordinates><panel_attributes>GroupsRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>260</x><y>377</y><w>130</w><h>39</h></coordinates><panel_attributes>Group</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>364</x><y>663</y><w>234</w><h>39</h></coordinates><panel_attributes>LightingMoodsRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>416</x><y>793</y><w>130</w><h>39</h></coordinates><panel_attributes>LightingMood</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>65</x><y>286</y><w>39</w><h>117</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>312</x><y>286</y><w>39</w><h>117</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>468</x><y>689</y><w>39</w><h>130</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;80;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>52</x><y>663</y><w>234</w><h>39</h></coordinates><panel_attributes>CompositionsRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>91</x><y>780</y><w>156</w><h>39</h></coordinates><panel_attributes>Composition</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>156</x><y>689</y><w>39</w><h>117</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>507</x><y>91</y><w>156</w><h>39</h></coordinates><panel_attributes>ArtNetController +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>507</x><y>195</y><w>156</w><h>52</h></coordinates><panel_attributes><<interface>> +LightControllable</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>572</x><y>117</y><w>39</w><h>104</h></coordinates><panel_attributes>lt=<<.</panel_attributes><additional_attributes>10;60;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>247</x><y>91</y><w>169</w><h>39</h></coordinates><panel_attributes>KiwiModelHandler</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>312</x><y>117</y><w>39</w><h>169</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;110;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>65</x><y>91</y><w>208</w><h>195</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;130;10;10;140;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>247</x><y>520</y><w>169</w><h>39</h></coordinates><panel_attributes>PresetsRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>273</x><y>611</y><w>104</w><h>39</h></coordinates><panel_attributes>Preset +</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>312</x><y>546</y><w>39</w><h>91</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;50;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>156</x><y>403</y><w>130</w><h>286</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>10;200;10;10;80;10</additional_attributes></element><element><id>Relation</id><coordinates><x>377</x><y>403</y><w>130</w><h>286</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>80;200;80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>156</x><y>260</y><w>130</w><h>143</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>10;10;40;10;40;90;80;90</additional_attributes></element><element><id>Relation</id><coordinates><x>65</x><y>403</y><w>39</w><h>286</h></coordinates><panel_attributes>lt=-></panel_attributes><additional_attributes>10;200;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>273</x><y>910</y><w>130</w><h>39</h></coordinates><panel_attributes>DmxValues</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>390</x><y>819</y><w>117</w><h>143</h></coordinates><panel_attributes>lt=<-</panel_attributes><additional_attributes>10;90;70;90;70;10</additional_attributes></element><element><id>Relation</id><coordinates><x>13</x><y>403</y><w>286</w><h>559</h></coordinates><panel_attributes>lt=<-</panel_attributes><additional_attributes>200;410;10;410;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>195</x><y>403</y><w>117</w><h>234</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>70;10;70;70;10;70;10;130;70;130;70;160</additional_attributes></element><element><id>UMLClass</id><coordinates><x>507</x><y>0</y><w>156</w><h>39</h></coordinates><panel_attributes>UdpListener</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>260</x><y>728</y><w>130</w><h>52</h></coordinates><panel_attributes><<interface>> +LightingScene</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>377</x><y>728</y><w>91</w><h>91</h></coordinates><panel_attributes>lt=<<.</panel_attributes><additional_attributes>10;10;50;10;50;50</additional_attributes></element><element><id>Relation</id><coordinates><x>208</x><y>728</y><w>78</w><h>78</h></coordinates><panel_attributes>lt=<<.</panel_attributes><additional_attributes>40;10;10;10;10;40</additional_attributes></element><element><id>Relation</id><coordinates><x>312</x><y>637</y><w>39</w><h>117</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>182</x><y>806</y><w>117</w><h>130</h></coordinates><panel_attributes>lt=<-</panel_attributes><additional_attributes>70;80;10;80;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>572</x><y>26</y><w>39</w><h>91</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;10;10;50</additional_attributes></element><element><id>Relation</id><coordinates><x>403</x><y>91</y><w>130</w><h>39</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>377</x><y>234</y><w>234</w><h>169</h></coordinates><panel_attributes>lt=<->>>></panel_attributes><additional_attributes>160;10;160;110;10;110</additional_attributes></element><element><id>UMLClass</id><coordinates><x>637</x><y>910</y><w>130</w><h>39</h></coordinates><panel_attributes>PropertyItem</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>390</x><y>117</y><w>78</w><h>429</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;310;10;260;40;260;40;60;10;60;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>728</x><y>91</y><w>195</w><h>39</h></coordinates><panel_attributes>ArtNetNodeRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>728</x><y>195</y><w>195</w><h>39</h></coordinates><panel_attributes>ArtNetNode</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>624</x><y>312</y><w>208</w><h>182</h></coordinates><panel_attributes>artNetPakages +-- ++ ArtCommand ++ ArtDataReply ++ ArtDataRequest ++ ArtDmx ++ ArtNetCodeLibrary ++ ArtPoll ++ ArtPollReply +valign=top +halign=left +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLPackage</id><coordinates><x>624</x><y>533</y><w>234</w><h>221</h></coordinates><panel_attributes>artNetCommands +-- ++ ActivateGroupCommand ++ ActivatePresetCommand ++ ClearPresetCommand ++ DeactivateGroupCommand ++ DeactivatePresetCommand ++ PresetActivatedCommand ++ PresetDeactivatedCommand ++ SetChannelStateCommand ++ SetPresetCommand +valign=top +halign=left +</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>650</x><y>91</y><w>104</w><h>39</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>60;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>806</x><y>117</y><w>39</w><h>104</h></coordinates><panel_attributes>lt=<->>>>></panel_attributes><additional_attributes>10;60;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>637</x><y>117</y><w>260</w><h>468</h></coordinates><panel_attributes>lt=.> +m2=<<use>></panel_attributes><additional_attributes>10;10;10;20;60;20;60;110;180;110;180;310;130;310;130;340</additional_attributes></element><element><id>Relation</id><coordinates><x>611</x><y>117</y><w>260</w><h>247</h></coordinates><panel_attributes>lt=.> +m2= <<use>></panel_attributes><additional_attributes>10;10;10;30;60;30;60;140;150;140;150;170</additional_attributes></element><element><id>Relation</id><coordinates><x>689</x><y>845</y><w>39</w><h>91</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;50;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>637</x><y>819</y><w>130</w><h>39</h></coordinates><panel_attributes>halign=center +valign=center +lt=. +Alle Klassen</panel_attributes><additional_attributes></additional_attributes></element></diagram> \ No newline at end of file diff --git a/doc/codeDocumentation/diagrams/classDiagramLightControlSoftwareModelPackage.pdf b/doc/codeDocumentation/diagrams/classDiagramLightControlSoftwareModelPackage.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c1b6235c517e0fbd03399f27c445bddbeeb4026c Binary files /dev/null and b/doc/codeDocumentation/diagrams/classDiagramLightControlSoftwareModelPackage.pdf differ diff --git a/doc/codeDocumentation/diagrams/classDiagramLightControlUnit.pdf b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit.pdf new file mode 100644 index 0000000000000000000000000000000000000000..04b514ec4468d215062e7306ad4b1caff49400f3 Binary files /dev/null and b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit.pdf differ diff --git a/doc/codeDocumentation/diagrams/classDiagramLightControlUnit.uxf b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit.uxf new file mode 100644 index 0000000000000000000000000000000000000000..74cac6233b5b08e2f43a0af7ed4760f7365ba1a8 --- /dev/null +++ b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit.uxf @@ -0,0 +1,75 @@ +<diagram program="umletino" version="15.1"><zoom_level>10</zoom_level><help_text>Space for diagram notes</help_text><element><id>UMLClass</id><coordinates><x>468</x><y>100</y><w>140</w><h>80</h></coordinates><panel_attributes><<struct>> +DmxChannel +-- +value: unsigned char +isUsed: bool +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>158</x><y>90</y><w>220</w><h>100</h></coordinates><panel_attributes><<struct>> +PresetStoredInfromation +-- +state: unsigned char +groupId: unsigned char +dmxChannels: DmxChannel[100] +</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>368</x><y>160</y><w>120</w><h>40</h></coordinates><panel_attributes>lt=->>>>> +m1=n +m2=1</panel_attributes><additional_attributes>100;10;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>78</x><y>220</y><w>340</w><h>210</h></coordinates><panel_attributes>Preset +-- +- eepromAdress: int +- presetLed: PresetLed +-- ++ Preset(eepromAdress: int, LedId: int) ++ loadPresetData(): void ++ setState(state: unsigned char): void ++ setChannelValue(channel: int, value: unsigned char): void ++ setGroupId(groupId: unsigned char): void ++ getGroupId(): unsigned char ++ getDmxChannel(): DmxChannel[]</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>258</x><y>180</y><w>30</w><h>60</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;10;10;40</additional_attributes></element><element><id>UMLClass</id><coordinates><x>298</x><y>470</y><w>440</w><h>200</h></coordinates><panel_attributes>PresetRepository +-- +- presets: Preset[6] +- dmxController: DmxController +-- ++ PresetRepository(eepromStartAdress: int, dmxController: DmxController) ++ activatePreset(presetId: int): void ++ deaktivatePreset(presetId: int): void ++ setPresetActive(presetId: int): void ++ setPresetDeactive(presetId: int): void ++ activateGroup(groupId: byte): void</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>838</x><y>470</y><w>350</w><h>70</h></coordinates><panel_attributes>DmxController +-- +-- ++ DmxController() ++ setChannelValue(channel: int, value: unsigned char): void</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>728</x><y>520</y><w>130</w><h>40</h></coordinates><panel_attributes>lt=<<<<- +m1=1 +m2=1</panel_attributes><additional_attributes>10;10;110;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>678</x><y>90</y><w>240</w><h>90</h></coordinates><panel_attributes>main +-- ++ presetRepository: PresetRepository ++ dmxController: DmxController ++ artNetController: ArtNetController +-- +</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>908</x><y>120</y><w>280</w><h>370</h></coordinates><panel_attributes>lt=->>>>> +m1=1 +m2=1</panel_attributes><additional_attributes>250;350;250;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>728</x><y>90</y><w>490</w><h>570</h></coordinates><panel_attributes>lt=->>>>> +m1=1 +m2=1</panel_attributes><additional_attributes>10;540;470;540;470;10;190;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>758</x><y>230</y><w>360</w><h>180</h></coordinates><panel_attributes>ArtNetController +-- +- presetRepository: PresetRepository +- dmxController: DmxController +-- ++ ArtNetController(pR: PresetRepository, dC: DmxController) ++ sendPresetActivated(presetId: int): void ++ sendPresetDeactivated(presetId: int): void</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>908</x><y>150</y><w>230</w><h>100</h></coordinates><panel_attributes>lt=->>>>> +m1=1 +m2=1</panel_attributes><additional_attributes>200;80;200;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>728</x><y>400</y><w>80</w><h>130</h></coordinates><panel_attributes>lt=<<<<- +m1=1 +m2=1</panel_attributes><additional_attributes>50;10;50;100;10;100</additional_attributes></element><element><id>Relation</id><coordinates><x>798</x><y>400</y><w>60</w><h>130</h></coordinates><panel_attributes>lt=<<<<- +m1=1 +m2=1</panel_attributes><additional_attributes>10;10;10;100;40;100</additional_attributes></element><element><id>Relation</id><coordinates><x>248</x><y>420</y><w>70</w><h>100</h></coordinates><panel_attributes>lt=->>>>> +m1=6 +m2=1</panel_attributes><additional_attributes>10;10;10;70;50;70</additional_attributes></element><element><id>UMLClass</id><coordinates><x>498</x><y>230</y><w>240</w><h>110</h></coordinates><panel_attributes>PresetLed +-- +- redPinOut: int +- greenPinOut: int +- bluePinOut: int +-- ++ PresetLed(r: int, g: int, b: int ) ++ setColor(r: bool, g: bool, b: bool): void</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>408</x><y>230</y><w>110</w><h>40</h></coordinates><panel_attributes>lt=->>>>> +m1=1 +m2=1</panel_attributes><additional_attributes>90;10;10;10</additional_attributes></element></diagram> \ No newline at end of file diff --git a/doc/codeDocumentation/diagrams/classDiagramLightControlUnit_simple.pdf b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit_simple.pdf new file mode 100644 index 0000000000000000000000000000000000000000..efed75be781d4598ea6ced19afefa0327b431a11 Binary files /dev/null and b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit_simple.pdf differ diff --git a/doc/codeDocumentation/diagrams/classDiagramLightControlUnit_simple.uxf b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit_simple.uxf new file mode 100644 index 0000000000000000000000000000000000000000..42508d7b7f59f058b0cfc80f56780a776d29d342 --- /dev/null +++ b/doc/codeDocumentation/diagrams/classDiagramLightControlUnit_simple.uxf @@ -0,0 +1,39 @@ +<diagram program="umletino" version="15.1"><zoom_level>12</zoom_level><element><id>UMLClass</id><coordinates><x>108</x><y>204</y><w>120</w><h>36</h></coordinates><panel_attributes>lt=.. +config</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>684</x><y>336</y><w>144</w><h>36</h></coordinates><panel_attributes>ArtNetController</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>204</x><y>612</y><w>144</w><h>36</h></coordinates><panel_attributes>lt=.. +DmxChannel +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>180</x><y>504</y><w>192</w><h>36</h></coordinates><panel_attributes>lt=.. +PresetStoredInformation +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>264</x><y>432</y><w>96</w><h>36</h></coordinates><panel_attributes>Preset</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>180</x><y>336</y><w>144</w><h>36</h></coordinates><panel_attributes>PresetRepository</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>84</x><y>432</y><w>96</w><h>36</h></coordinates><panel_attributes>PresetLed</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>444</x><y>336</y><w>144</w><h>36</h></coordinates><panel_attributes>DmxController +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>444</x><y>204</y><w>144</w><h>36</h></coordinates><panel_attributes>LightControlUnit</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>684</x><y>516</y><w>144</w><h>36</h></coordinates><panel_attributes>lt=.. +ArtNetPackages +</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>72</x><y>168</y><w>792</w><h>108</h></coordinates><panel_attributes>lt=. +Hauptapplikation</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>684</x><y>444</y><w>120</w><h>36</h></coordinates><panel_attributes>lt=.. +ArtCommands +</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>216</x><y>204</y><w>252</w><h>36</h></coordinates><panel_attributes>lt=<-</panel_attributes><additional_attributes>10;10;190;10</additional_attributes></element><element><id>Relation</id><coordinates><x>312</x><y>336</y><w>156</w><h>48</h></coordinates><panel_attributes>lt=<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>10;10;110;10</additional_attributes></element><element><id>Relation</id><coordinates><x>240</x><y>216</y><w>228</w><h>144</h></coordinates><panel_attributes>lt=<<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>170;10;10;10;10;100</additional_attributes></element><element><id>Relation</id><coordinates><x>576</x><y>216</y><w>216</w><h>144</h></coordinates><panel_attributes>lt=<<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>10;10;150;10;150;100</additional_attributes></element><element><id>Relation</id><coordinates><x>504</x><y>228</y><w>48</w><h>132</h></coordinates><panel_attributes>lt=<<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>10;10;10;90</additional_attributes></element><element><id>Relation</id><coordinates><x>576</x><y>336</y><w>132</w><h>48</h></coordinates><panel_attributes>lt=<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>90;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>804</x><y>360</y><w>36</w><h>180</h></coordinates><panel_attributes>lt=<-</panel_attributes><additional_attributes>10;130;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>732</x><y>360</y><w>36</w><h>108</h></coordinates><panel_attributes>lt=<-</panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>312</x><y>360</y><w>420</w><h>84</h></coordinates><panel_attributes>lt=<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>320;10;320;50;80;50;80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>264</x><y>528</y><w>60</w><h>108</h></coordinates><panel_attributes>lt=<->>>>> +m1=100 +m2=1</panel_attributes><additional_attributes>10;70;10;10</additional_attributes></element><element><id>UMLClass</id><coordinates><x>636</x><y>288</y><w>228</w><h>396</h></coordinates><panel_attributes>lt=. +valign=bottom +halign=center +Art-Net</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>396</x><y>288</y><w>228</w><h>396</h></coordinates><panel_attributes>lt=. +valign=bottom +halign=center +DMX</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>72</x><y>288</y><w>312</w><h>396</h></coordinates><panel_attributes>lt=. +valign=bottom +halign=center +Presets</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>300</x><y>456</y><w>36</w><h>72</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;40;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>168</x><y>444</y><w>120</w><h>48</h></coordinates><panel_attributes>lt=<<<<<-> +m1=1 +m2=1</panel_attributes><additional_attributes>80;10;10;10</additional_attributes></element><element><id>Relation</id><coordinates><x>240</x><y>360</y><w>108</w><h>96</h></coordinates><panel_attributes>lt=<<<<<-> +m1=1 +m2=6</panel_attributes><additional_attributes>10;10;10;40;60;40;60;60</additional_attributes></element></diagram> \ No newline at end of file diff --git a/doc/codeDocumentation/requierments/bullet points.txt b/doc/codeDocumentation/requierments/bullet points.txt new file mode 100644 index 0000000000000000000000000000000000000000..6f24e92c71cde51fe0214f769a79f2220a2cb76e --- /dev/null +++ b/doc/codeDocumentation/requierments/bullet points.txt @@ -0,0 +1,85 @@ +- kontinuierliches Senden der DMX-Werte +- aktivieren und deaktivieren von Presets + -> Prüfen, ob andere Gruppen Teilaktiv sind +- Wenn eine Gruppe aktiv gesetzt wird, dann müssen alle Presets der Gruppe auf Aktiv gehen + - Nur die Schnellauswahltaste, nicht den Preset selber aktivieren +- Bei jeder Änderung eines Channels muss getestet werden, ob eine Gruppe auf Teilaktiv gestellt wird +- Alle Presetdaten müssen gespeichert werden, bei jeder Änderung. + +Event: + Preset aktivieren: + -> Preset aktivieren + -> setzten der LED + -> setzten des Prest-Status + -> Preset Daten speichern + -> setzen der DMX-Werte + -> Andere Presets der Gruppe deaktivieren. + -> Presets anderer Gruppen auf State prüfen + -> setzten des Prest-Status + -> Preset Daten speichern + + Preset deaktivieren: + -> Preset deaktivieren + -> setzten der LED + -> setzten des Prest-Status + -> Preset Daten speichern + -> setzen der DMX-Werte + -> Andere Presets der Gruppe deaktivieren. + -> Presets anderer Gruppen auf State prüfen + -> setzten des Prest-Status + -> Preset Daten speichern + + Preset leeren: + -> Preset deaktivieren + -> Preset leeren + + Setzen eines Preset Wertes: + -> Presetwert im Preset setzten + -> Preset speichern + Falls Preset aktiv + -> DMX-Wert senden + -> Andere Presets prüfen, ob diese nun aktiv sind. + + Gruppe für Preset setzen + -> Preset Gruppe setzten + Falls aktiv: + -> Preset der anderen Gruppen deaktivieren + + + Gruppe aktivieren + -> Alle Presets der Gruppe auf Part activ setzten + -> Werte Speichern + + Gruppe deaktivieren + -> Alle Presets der Gruppe deaktivieren + -> Werte Speichern + + Status abfragen + -> + + + +UDP Paket Länge + ArtPoll (Empfang A; Senden J) + min 14 + max 22 + ArtPollReply (Empfang J; Senden A) + min 207 + max 236 + ArtCommand (Empfang A,J; Senden A,J) + min 16 + max 528 + ArtDataRequest (Empfang A; Senden J) + min/max 40 + ArtDataReply (Empfang J; Senden A) + min 20 + max 532 + ArtDmx (Empfang A; Senden J) + min 20 + max 530 + +Empfangen A: max 530 +Empfangen J: max 532 + +Senden A: max 532 +Senden J: max 530 \ No newline at end of file diff --git a/src/lightControlSoftware/.classpath b/src/lightControlSoftware/.classpath new file mode 100644 index 0000000000000000000000000000000000000000..0414b1474d9e05cb8c7b4b0e3a68e2c3f09ccd75 --- /dev/null +++ b/src/lightControlSoftware/.classpath @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="ressourcen"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/javafx-jre-16"> + <attributes> + <attribute name="module" value="true"/> + </attributes> + </classpathentry> + <classpathentry kind="lib" path="C:/Program Files/Java/javafx-sdk-16/lib/gson-2.10.1.jar"/> + <classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JavaFX16"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-19"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/src/lightControlSoftware/.gitignore b/src/lightControlSoftware/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..ae3c1726048cd06b9a143e0376ed46dd9b9a8d53 --- /dev/null +++ b/src/lightControlSoftware/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/src/lightControlSoftware/ressourcen/images/Delete.png b/src/lightControlSoftware/ressourcen/images/Delete.png new file mode 100644 index 0000000000000000000000000000000000000000..7a46061740c00b1671f9f5097d1a11ddc356430f Binary files /dev/null and b/src/lightControlSoftware/ressourcen/images/Delete.png differ diff --git a/src/lightControlSoftware/ressourcen/images/Edit.png b/src/lightControlSoftware/ressourcen/images/Edit.png new file mode 100644 index 0000000000000000000000000000000000000000..1b50153a9c18aba044bebb2401adfb0ab501a75a Binary files /dev/null and b/src/lightControlSoftware/ressourcen/images/Edit.png differ diff --git a/src/lightControlSoftware/ressourcen/images/Icon Test.png b/src/lightControlSoftware/ressourcen/images/Icon Test.png new file mode 100644 index 0000000000000000000000000000000000000000..a1faca5852d81b9f013d7036d354fed94ed78c6f Binary files /dev/null and b/src/lightControlSoftware/ressourcen/images/Icon Test.png differ diff --git a/src/lightControlSoftware/ressourcen/images/Kiwi_Logo.png b/src/lightControlSoftware/ressourcen/images/Kiwi_Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..258fe499e53b8097473edb430baf08089ed936f9 Binary files /dev/null and b/src/lightControlSoftware/ressourcen/images/Kiwi_Logo.png differ diff --git a/src/lightControlSoftware/ressourcen/lib/ImageButton.jar b/src/lightControlSoftware/ressourcen/lib/ImageButton.jar new file mode 100644 index 0000000000000000000000000000000000000000..4149d003c86683b837ba7e8f278ee6c432498bdb Binary files /dev/null and b/src/lightControlSoftware/ressourcen/lib/ImageButton.jar differ diff --git a/src/lightControlSoftware/ressourcen/lib/NumberField.jar b/src/lightControlSoftware/ressourcen/lib/NumberField.jar new file mode 100644 index 0000000000000000000000000000000000000000..cc1ea19b2c35c6ef752a3f36173ed5ebc89a61aa Binary files /dev/null and b/src/lightControlSoftware/ressourcen/lib/NumberField.jar differ diff --git a/src/lightControlSoftware/ressourcen/lib/TreeStageSwitchButton.jar b/src/lightControlSoftware/ressourcen/lib/TreeStageSwitchButton.jar new file mode 100644 index 0000000000000000000000000000000000000000..8bb9d01cb29dcfab2c7d9ff49d9fec20de83002f Binary files /dev/null and b/src/lightControlSoftware/ressourcen/lib/TreeStageSwitchButton.jar differ diff --git a/src/lightControlSoftware/ressourcen/style/Style.css b/src/lightControlSoftware/ressourcen/style/Style.css new file mode 100644 index 0000000000000000000000000000000000000000..cba15657d430c52627de8f7c009e7ff428401732 --- /dev/null +++ b/src/lightControlSoftware/ressourcen/style/Style.css @@ -0,0 +1,93 @@ +.root { + -fx-background-color: white; +} + +BorderPane { + -fx-background-color: white; +} + +ScrollPane { + -fx-background-color: white; +} + +SplitPane { + -fx-background-color: white; +} + +FlowPane { + -fx-background-color: white; +} + +Button { + -fx-background-radius: 25; +} + +.list-cell { + -fx-background-color: transparent; +} + +.white-background { + -fx-background-color: white; +} + +.section { + -fx-border-color: gray; + -fx-border-width: 2px; + -fx-border-radius: 5px; + -fx-padding: 10 5 5 5; +} + +.section-headline { + -fx-background-color: white; + -fx-padding: 0 5 0 5; +} + +.list-item { + -fx-border-color: black; + -fx-border-width: 1px; + -fx-border-radius: 5px; + -fx-background-color: lightgray; + -fx-background-radius: 5px; +} + +.item-diselected { + -fx-border-color: black; + -fx-border-width: 1px; + -fx-border-radius: 5px; +} + +.item-selected { + -fx-border-color: orange; + -fx-border-width: 2px; + -fx-border-radius: 5px; +} + +.lable-box { + -fx-border-color: black; + -fx-border-width: 1px; + -fx-border-radius: 5px; +} + +.footer { + -fx-background-color: lightgray +} + +.text-color-black { + -fx-text-fill: black +} + +.combo-box .list-cell +{ + -fx-background: white; + -fx-text-fill: black; +} + +.combo-box .list-view .list-cell:focused { + -fx-background-color : orange; + -fx-text-fill: white; +} + +.combo-box .list-view .list-cell:hover { + -fx-background-color : orange; + -fx-text-fill: white; +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/appliaction/MainKiwi.java b/src/lightControlSoftware/src/appliaction/MainKiwi.java new file mode 100644 index 0000000000000000000000000000000000000000..7af165cec8bf91b5600c6ad9878c08b01099ff17 --- /dev/null +++ b/src/lightControlSoftware/src/appliaction/MainKiwi.java @@ -0,0 +1,33 @@ +package appliaction; + +import javafx.application.Application; +import javafx.stage.Stage; +import model.KiwiModelHandler; +import view.KiwiViewHandler; +import viewModel.KiwiViewModelHandler; + +public class MainKiwi extends Application{ + + private KiwiModelHandler modelHandler; + private KiwiViewModelHandler viewModelHandler; + private KiwiViewHandler viewHandler; + + @Override + public void start(Stage primaryStage) throws Exception { + this.modelHandler = new KiwiModelHandler(); + this.modelHandler.testModels(); + this.viewModelHandler = new KiwiViewModelHandler(modelHandler); + this.viewHandler = new KiwiViewHandler(primaryStage, viewModelHandler); + + viewHandler.start(); + } + + public static void main(String[] args) { + launch(args); + } + + @Override + public void stop(){ + System.exit(0); + } +} diff --git a/src/lightControlSoftware/src/model/KiwiModelHandler.java b/src/lightControlSoftware/src/model/KiwiModelHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..4651e215adf66d4a4097e5ece1517cce563f3e3c --- /dev/null +++ b/src/lightControlSoftware/src/model/KiwiModelHandler.java @@ -0,0 +1,173 @@ +package model; + +import model.fixture.DmxValues; +import model.fixture.Fixture; +import model.fixture.FixtureRepository; +import model.group.Group; +import model.group.GroupReposirory; +import model.lightController.LightControllable; +import model.lightController.artNet.ArtNetController; +import model.lightingScene.composition.Composition; +import model.lightingScene.lightingMood.LightingMood; +import model.preset.PresetRepository; + +public class KiwiModelHandler { + private static FixtureRepository fixtureRepository; + private static GroupReposirory groupReposirory; + private static LightControllable lightController; + private static PresetRepository presetRepository; + + + public static FixtureRepository getFixtureRepository() { + return KiwiModelHandler.fixtureRepository; + } + + public static GroupReposirory getGroupReposirory() { + return KiwiModelHandler.groupReposirory; + } + + public static LightControllable getLightController() { + return KiwiModelHandler.lightController; + } + + public static PresetRepository getPresetRepository() { + return KiwiModelHandler.presetRepository; + } + + public static ArtNetController getArtNetController() { + return (ArtNetController) KiwiModelHandler.lightController; + } + + public KiwiModelHandler() { + KiwiModelHandler.fixtureRepository = new FixtureRepository(); + KiwiModelHandler.groupReposirory = new GroupReposirory(); + KiwiModelHandler.presetRepository = new PresetRepository(); + KiwiModelHandler.lightController = new ArtNetController(KiwiModelHandler.presetRepository); + KiwiModelHandler.presetRepository.loadPrests(); + } + + private void tempSetup() { + // Lampen hinzufügen + fixtureRepository.addFixture(new Fixture("Wohnzimmer Fernseher", 1)); + fixtureRepository.addFixture(new Fixture("Wohnzimmer Decke", 6)); + fixtureRepository.addFixture(new Fixture("Küche", 11)); + fixtureRepository.addFixture(new Fixture("Schlafzimmer", 16)); + + // Gruppe Wohnzimmer erstellen + Group wohnzimmer = new Group("Wohnzimmer", lightController); + wohnzimmer.addFixture(fixtureRepository.getFixture("Wohnzimmer Fernseher")); + wohnzimmer.addFixture(fixtureRepository.getFixture("Wohnzimmer Decke")); + insertLightingMood(wohnzimmer); + + // Gruppe Küche erstellen + Group kueche = new Group("Küche", lightController); + kueche.addFixture(fixtureRepository.getFixture("Küche")); + insertLightingMood(kueche); + + // Gruppe Schlafzimmer erstellen + Group schlafzimmer = new Group("Schlafzimmer", lightController); + schlafzimmer.addFixture(fixtureRepository.getFixture("Schlafzimmer")); + insertLightingMood(schlafzimmer); + + // Gruppe Etage erstellen + Group etage = new Group("Etage", lightController); + etage.addFixture(fixtureRepository.getFixture("Wohnzimmer Fernseher")); + etage.addFixture(fixtureRepository.getFixture("Wohnzimmer Decke")); + etage.addFixture(fixtureRepository.getFixture("Küche")); + etage.addFixture(fixtureRepository.getFixture("Schlafzimmer")); + insertLightingMood(etage); + + // Gruppen dem Repro hinzufügen + groupReposirory.addGroup(wohnzimmer); + groupReposirory.addGroup(kueche); + groupReposirory.addGroup(schlafzimmer); + groupReposirory.addGroup(etage); + + + // Preset setzten + presetRepository.getPreset(0).setGroup(wohnzimmer); + presetRepository.getPreset(0).setLightingScene(wohnzimmer.getLightingMoodRepository().getLightingMood("Rot")); + + presetRepository.getPreset(1).setGroup(wohnzimmer); + presetRepository.getPreset(1).setLightingScene(wohnzimmer.getLightingMoodRepository().getLightingMood("Grün")); + + + Composition filmeAbend = new Composition("Filmeabend"); + filmeAbend.setDmxValuesForFixture("Wohnzimmer Fernseher", new DmxValues((byte)255, (byte)0, (byte)0, (byte)0, (byte)255)); + filmeAbend.setDmxValuesForFixture("Wohnzimmer Decke", new DmxValues((byte)100, (byte)0, (byte)255, (byte)255, (byte)255)); + wohnzimmer.addComposition(filmeAbend); + + // Presets setzen +// presetRepository.getPreset(0).setGroup(wohnzimmer); +// presetRepository.getPreset(0).setLightingScene(blue); +// presetRepository.getPreset(0).updatePreset(); + +// presetRepository.getPreset(5).setGroup(etage); +// presetRepository.getPreset(5).setLightingScene(white); +// presetRepository.getPreset(5).updatePreset(); + + + +// lightController.clearPreset(0); +// lightController.setPreset(0, (byte)1, 1, (byte)0); +// lightController.setPreset(0, (byte)1, 2, (byte)0); +// lightController.setPreset(0, (byte)1, 3, (byte)255); +// lightController.setPreset(0, (byte)1, 4, (byte)255); +// lightController.setPreset(0, (byte)1, 5, (byte)0); +// lightController.setPreset(0, (byte)1, 6, (byte)0); +// lightController.setPreset(0, (byte)1, 7, (byte)0); +// lightController.setPreset(0, (byte)1, 8, (byte)255); +// lightController.setPreset(0, (byte)1, 9, (byte)255); +// lightController.setPreset(0, (byte)1, 10, (byte)0); + } + + private void insertLightingMood(Group group) { + LightingMood red = new LightingMood("Rot"); + LightingMood green = new LightingMood("Grün"); + LightingMood blue = new LightingMood("Blau"); + LightingMood white = new LightingMood("Weiß"); + + red.setDmxValues(new DmxValues((byte)255, (byte)0, (byte)255, (byte)0, (byte)0)); + green.setDmxValues(new DmxValues((byte)255, (byte)0, (byte)0, (byte)255, (byte)0)); + blue.setDmxValues(new DmxValues((byte)255, (byte)0, (byte)0, (byte)0, (byte)255)); + white.setDmxValues(new DmxValues((byte)100, (byte)0, (byte)255, (byte)255, (byte)255)); + + group.addLightingMood(red); + group.addLightingMood(green); + group.addLightingMood(blue); + group.addLightingMood(white); + } + + private void tempAction() { + Group wohnzimmer = KiwiModelHandler.groupReposirory.getGroup("Wohnzimmer"); + Group kueche = KiwiModelHandler.groupReposirory.getGroup("Küche"); + Group schlafzimmer = KiwiModelHandler.groupReposirory.getGroup("Schlafzimmer"); + Group etage = KiwiModelHandler.groupReposirory.getGroup("Etage"); + + wohnzimmer.activateLightingMood(wohnzimmer.getLightingMoodRepository().getLightingMood("Grün")); + wohnzimmer.activate(); + + kueche.activateLightingMood(kueche.getLightingMoodRepository().getLightingMood("Rot")); + kueche.activate(); + + schlafzimmer.activateLightingMood(schlafzimmer.getLightingMoodRepository().getLightingMood("Blau")); + schlafzimmer.activate(); + +// etage.activateLightingMood(etage.getLightingMoodRepository().getLightingMood("Rot")); +// etage.activate(); + } + + public void testModels() { + this.tempSetup(); + // Nodes verbinden + //this.lightController.connectToNodes(); + //this.tempAction(); + //this.lightController.connectToNodes(); + } + + public void clearRepros() { + KiwiModelHandler.fixtureRepository.clearRepro(); + KiwiModelHandler.groupReposirory.clearRepro(); + + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/fixture/DmxValues.java b/src/lightControlSoftware/src/model/fixture/DmxValues.java new file mode 100644 index 0000000000000000000000000000000000000000..2ed01ba33878efbdcdb32ab7290f02378d563b7c --- /dev/null +++ b/src/lightControlSoftware/src/model/fixture/DmxValues.java @@ -0,0 +1,69 @@ +package model.fixture; + +import java.io.Serializable; + +import model.generic.PropertyItem; + +public class DmxValues extends PropertyItem implements Serializable{ + protected byte intensityMain = 0; + protected byte stropeRate = 0; + protected byte intensityRed = 0; + protected byte intensityGreen = 0; + protected byte intensityBlue = 0; + + public DmxValues() {} + + public DmxValues(byte intensityMain, byte stropeRate, byte intensityRed, byte intensityGreen, byte intensityBlue) { + super(); + this.intensityMain = intensityMain; + this.stropeRate = stropeRate; + this.intensityRed = intensityRed; + this.intensityGreen = intensityGreen; + this.intensityBlue = intensityBlue; + } + + public byte getIntensityMain() { + return intensityMain; + } + + public byte getStropeRate() { + return stropeRate; + } + + public byte getIntensityRed() { + return intensityRed; + } + + public byte getIntensityGreen() { + return intensityGreen; + } + + public byte getIntensityBlue() { + return intensityBlue; + } + + public void setIntensityMain(byte intensityMain) { + this.propertySupport.firePropertyChange("intensityMain", Byte.toUnsignedInt(this.intensityMain), Byte.toUnsignedInt(intensityMain)); + this.intensityMain = intensityMain; + } + + public void setStropeRate(byte stropeRate) { + this.propertySupport.firePropertyChange("stropeRate", Byte.toUnsignedInt(this.stropeRate), Byte.toUnsignedInt(stropeRate)); + this.stropeRate = stropeRate; + } + + public void setIntensityRed(byte intensityRed) { + this.propertySupport.firePropertyChange("intensityRed", Byte.toUnsignedInt(this.intensityRed), Byte.toUnsignedInt(intensityRed)); + this.intensityRed = intensityRed; + } + + public void setIntensityGreen(byte intensityGreen) { + this.propertySupport.firePropertyChange("intensityGreen", Byte.toUnsignedInt(this.intensityGreen), Byte.toUnsignedInt(intensityGreen)); + this.intensityGreen = intensityGreen; + } + + public void setIntensityBlue(byte intensityBlue) { + this.propertySupport.firePropertyChange("intensityBlue", Byte.toUnsignedInt(this.intensityBlue), Byte.toUnsignedInt(intensityBlue)); + this.intensityBlue = intensityBlue; + } +} diff --git a/src/lightControlSoftware/src/model/fixture/Fixture.java b/src/lightControlSoftware/src/model/fixture/Fixture.java new file mode 100644 index 0000000000000000000000000000000000000000..c9a28422a094c150dcd6b11785d8de3b56e60fa9 --- /dev/null +++ b/src/lightControlSoftware/src/model/fixture/Fixture.java @@ -0,0 +1,104 @@ +package model.fixture; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import model.KiwiModelHandler; +import model.generic.PropertyItem; +import model.lightController.LightControllable; + +public class Fixture extends PropertyItem{ + private String name; + private int address; + private int numberOfChannel = 5; + private boolean isActive; + private DmxValues dmxValues; + private LightControllable lightController; + private PropertyChangeListener dmxValueListener; + + public Fixture(String name, int adress) { + super(); + this.name = name; + this.address = adress; + this.dmxValues = new DmxValues(); + this.lightController = KiwiModelHandler.getLightController(); + this.dmxValueListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + sendDmxValue(); + } + }; + this.dmxValues.addPropertyChangeListener(this.dmxValueListener); + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.propertySupport.firePropertyChange("name", this.name, name); + this.name = name; + } + + public int getAddress() { + return this.address; + } + + public void setAddress(int address) { + this.propertySupport.firePropertyChange("address", this.address, address); + this.address = address; + } + + public boolean isActive() { + return this.isActive; + } + + public DmxValues getDmxValues() { + return this.dmxValues; + } + + public void setDmxValues(DmxValues dmxValues) { + this.dmxValues.removePropertyChangeListener(dmxValueListener); + this.dmxValues = dmxValues; + this.dmxValues.addPropertyChangeListener(dmxValueListener); + if(this.isActive) { + this.sendDmxValue(); + } + } + + public void activate() { + if(!this.isActive) { + this.isActive = true; + this.propertySupport.firePropertyChange("isActive", false, true); + this.sendDmxValue(); + } + + } + + public void deactivate() { + if(this.isActive) { + this.isActive = false; + this.propertySupport.firePropertyChange("isActive", true, false); + this.sendDmxValue(); + } + } + + private void sendDmxValue(){ + if(isActive) { + this.lightController.setDmxValue(this.address, this.dmxValues.getIntensityRed()); + this.lightController.setDmxValue(this.address + 1, this.dmxValues.getIntensityGreen()); + this.lightController.setDmxValue(this.address + 2, this.dmxValues.getIntensityBlue()); + this.lightController.setDmxValue(this.address + 3, this.dmxValues.getIntensityMain()); + this.lightController.setDmxValue(this.address + 4, this.dmxValues.getStropeRate()); + + for(int i = 0; i < this.numberOfChannel; i++) { + this.lightController.activateDmxChannel(this.address + i); + } + } else { + for(int i = 0; i < this.numberOfChannel; i++) { + this.lightController.sendDmxValue(this.address + i, (byte)0x00); + this.lightController.deactivateDmxChannel(this.address + i); + } + } + } +} diff --git a/src/lightControlSoftware/src/model/fixture/FixtureRepository.java b/src/lightControlSoftware/src/model/fixture/FixtureRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..c70513fabba7950edede6e4c3a8355ee72dfcd50 --- /dev/null +++ b/src/lightControlSoftware/src/model/fixture/FixtureRepository.java @@ -0,0 +1,80 @@ +package model.fixture; + +import java.util.Map; + +import model.generic.PropertyItem; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.HashMap; + +public class FixtureRepository extends PropertyItem{ + private Map<String, Fixture> fixtures; + private int activeFixtures; + private PropertyChangeListener fixtureListener; + + public FixtureRepository() { + this.fixtures = new HashMap<>(); + this.activeFixtures = 0; + this.fixtureListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("isActive")) { + if((boolean) event.getNewValue()) { + addNumberOfActiveFixtures(); + } else { + subNumberOfActiveFixtures(); + } + } + } + }; + } + + public void addFixture(Fixture fixture) { + if(this.fixtures.containsKey(fixture.getName())) { + throw new IllegalArgumentException("Es existiert bereits eine Lampe mit diesem Namen"); + } + + this.fixtures.put(fixture.getName(), fixture); + this.propertySupport.firePropertyChange("fixtures", null, fixture); + + fixture.addPropertyChangeListener(this.fixtureListener); + } + + private void addNumberOfActiveFixtures() { + this.propertySupport.firePropertyChange("activeFixtures", this.activeFixtures, this.activeFixtures+1); + this.activeFixtures++; + } + + private void subNumberOfActiveFixtures() { + this.propertySupport.firePropertyChange("activeFixtures", this.activeFixtures, this.activeFixtures-1); + this.activeFixtures--; + } + + public int getActiveFixturesCount() { + return this.activeFixtures; + } + + public Fixture getFixture(String name) { + return this.fixtures.get(name); + } + + public void removeFixture(String name) { + this.fixtures.get(name).deactivate(); + this.fixtures.get(name).removePropertyChangeListener(fixtureListener); + this.propertySupport.firePropertyChange("fixtures", this.fixtures.get(name), null); + this.fixtures.remove(name); + } + + public Map<String, Fixture> getFixtureMap() { + return this.fixtures; + } + + + + public void clearRepro() { + Map.copyOf(this.fixtures).forEach((String name, Fixture fixture) -> { + this.removeFixture(name); + }); + this.activeFixtures = 0; + } +} diff --git a/src/lightControlSoftware/src/model/generic/PropertyItem.java b/src/lightControlSoftware/src/model/generic/PropertyItem.java new file mode 100644 index 0000000000000000000000000000000000000000..28a60b7e9894c47e3a85f398264991b5f5523c7f --- /dev/null +++ b/src/lightControlSoftware/src/model/generic/PropertyItem.java @@ -0,0 +1,16 @@ +package model.generic; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public abstract class PropertyItem { + protected final PropertyChangeSupport propertySupport = new PropertyChangeSupport(this); + + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertySupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertySupport.removePropertyChangeListener(listener); + } +} diff --git a/src/lightControlSoftware/src/model/group/Group.java b/src/lightControlSoftware/src/model/group/Group.java new file mode 100644 index 0000000000000000000000000000000000000000..a1b2dc51d09b79b03c00f11b60c1459570fb62ec --- /dev/null +++ b/src/lightControlSoftware/src/model/group/Group.java @@ -0,0 +1,213 @@ +package model.group; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import model.fixture.DmxValues; +import model.fixture.Fixture; +import model.fixture.FixtureRepository; +import model.generic.PropertyItem; +import model.lightController.LightControllable; +import model.lightingScene.LightingScene; +import model.lightingScene.LightingScene.LightingSceneType; +import model.lightingScene.composition.Composition; +import model.lightingScene.composition.CompositionRepository; +import model.lightingScene.lightingMood.LightingMood; +import model.lightingScene.lightingMood.LightingMoodRepository; + +public class Group extends PropertyItem{ + private byte id; + private String name; + private State currentState = State.DEAKTIV; + private LightingScene currentLightingScene; + private LightControllable lightController; + private FixtureRepository fixtureRepository; + private LightingMoodRepository lightingMoodRepository; + private CompositionRepository compositionRepository; + private PropertyChangeListener fixtureRepositoryListener; + + public static enum State { + AKTIV, + PARTAKTIV, + DEAKTIV + } + + + public Group(String name, LightControllable lightController) { + super(); + this.name = name; + this.lightController = lightController; + this.currentLightingScene = null; + this.fixtureRepository = new FixtureRepository(); + this.lightingMoodRepository = new LightingMoodRepository(); + this.compositionRepository = new CompositionRepository(); + this.fixtureRepositoryListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("activeFixtures")) { + int activeFixtures= (int)event.getNewValue(); + if(activeFixtures == 0) { + setCurrentState(State.DEAKTIV); + } else if(activeFixtures < fixtureRepository.getFixtureMap().size()) { + setCurrentState(State.PARTAKTIV); + } else if(activeFixtures == fixtureRepository.getFixtureMap().size()) { + setCurrentState(State.AKTIV); + } + } + } + }; + } + + public byte getId() { + return this.id; + } + + public void setId(byte id) { + this.propertySupport.firePropertyChange("id", this.id, id); + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.propertySupport.firePropertyChange("name", this.name, name); + this.name = name; + } + + public State getCurrentState() { + return this.currentState; + } + + public void setCurrentState(State currentState) { + this.propertySupport.firePropertyChange("currentState", this.currentState, currentState); + this.currentState = currentState; + } + + public void addFixture(Fixture fixture) { + this.fixtureRepository.addFixture(fixture); + this.compositionRepository.getCompositionMap().forEach((String name, Composition composition) -> { + composition.setDmxValuesForFixture(fixture.getName(), new DmxValues()); + }); + + if(this.currentLightingScene != null) { + if(this.currentLightingScene.getLightingSceneType() == LightingSceneType.LIGHTING_MOOD) { + fixture.setDmxValues(((LightingMood) this.currentLightingScene).getDmxValues()); + } else if(this.currentLightingScene.getLightingSceneType() == LightingSceneType.COMPOSITION) { + fixture.setDmxValues(((Composition) this.currentLightingScene).getDmxValuesForFixture(fixture.getName())); + } + } + this.fixtureRepository.addPropertyChangeListener(this.fixtureRepositoryListener); + if(this.currentState == State.AKTIV) { + fixture.activate(); + } + } + + public void addLightingMood(LightingMood lightingMood) { + this.lightingMoodRepository.addLightingMood(lightingMood); + } + + public void addComposition(Composition composition) { + this.compositionRepository.addComposition(composition); + } + + public void removeFixture(Fixture fixture) { + fixture.removePropertyChangeListener(this.fixtureRepositoryListener); + this.fixtureRepository.removeFixture(fixture.getName()); + this.compositionRepository.getCompositionMap().forEach((String name, Composition composition) -> { + composition.removeFixtureFromComposition(fixture.getName()); + }); + fixture.deactivate(); + } + + public void removeLightingMood(LightingMood lightingMood) { + this.lightingMoodRepository.removeLightingMood(lightingMood.getName()); + } + + public void removeComposition(Composition composition) { + this.compositionRepository.removeComposition(composition.getName()); + } + + public void activateLightingMood(LightingMood lightingMood) { + if(lightingMood != null) { + if(this.currentLightingScene != null) { + this.currentLightingScene.deactivate(); + } + this.currentLightingScene = lightingMood; + if(!lightingMood.isActive()) { + lightingMood.activate(); + } + + + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + fixture.setDmxValues(lightingMood.getDmxValues()); + }); + } + if(this.currentState != State.DEAKTIV) { + this.lightController.sendDmxValue(); + } + } + + public void deactivateLightingMood(LightingMood lightingMood) { + lightingMood.deactivate(); + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + fixture.setDmxValues(new DmxValues()); + }); + this.lightController.sendDmxValue(); + } + + public void activateComposition(Composition composition) { + if(this.currentLightingScene != null) { + this.currentLightingScene.deactivate(); + } + + this.currentLightingScene = composition; + if(!composition.isActive()) { + composition.activate(); + } + + + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + fixture.setDmxValues(composition.getDmxValuesForFixture(name)); + }); + if(this.currentState != State.DEAKTIV) { + this.lightController.sendDmxValue(); + } + } + + public void deactivateComposition(Composition composition) { + composition.deactivate(); + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + fixture.setDmxValues(new DmxValues()); + }); + this.lightController.sendDmxValue(); + } + + public FixtureRepository getFixtureRepository() { + return this.fixtureRepository; + } + + public LightingMoodRepository getLightingMoodRepository() { + return this.lightingMoodRepository; + } + + public CompositionRepository getCompositionRepository() { + return this.compositionRepository; + } + + public void activate() { + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + fixture.activate(); + }); + this.lightController.sendDmxValue(); + this.lightController.activateGroup(this.id); + } + + public void deactivate() { + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + fixture.deactivate(); + }); + this.lightController.sendDmxValue(); + this.lightController.deactivateGroup(this.id); + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/group/GroupReposirory.java b/src/lightControlSoftware/src/model/group/GroupReposirory.java new file mode 100644 index 0000000000000000000000000000000000000000..1643aa6fcc9ba1b8e845db59458293fef8308dcb --- /dev/null +++ b/src/lightControlSoftware/src/model/group/GroupReposirory.java @@ -0,0 +1,45 @@ +package model.group; + +import java.util.Map; +import model.generic.PropertyItem; +import java.util.HashMap; + +public class GroupReposirory extends PropertyItem{ + private Map<String, Group> groups; + private byte currentGroupId = 1; + + public GroupReposirory() { + this.groups = new HashMap<>(); + } + + public void addGroup(Group group) { + if(this.groups.containsKey(group.getName())) { + throw new IllegalArgumentException("Es existiert bereits eine Gruppe mit diesem Namen"); + } + group.setId(currentGroupId); + currentGroupId++; + this.groups.put(group.getName(), group); + this.propertySupport.firePropertyChange("groups", null, group); + } + + public Group getGroup(String name) { + return groups.get(name); + } + + public void removeGroup(String name) { + this.groups.get(name).deactivate(); + this.propertySupport.firePropertyChange("groups", this.groups.get(name), null); + this.groups.remove(name); + } + + public Map<String, Group> getGroupsMap() { + return this.groups; + } + + public void clearRepro() { + Map.copyOf(this.groups).forEach((String name, Group group) -> { + this.removeGroup(name); + }); + this.currentGroupId = 0; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/LightControllable.java b/src/lightControlSoftware/src/model/lightController/LightControllable.java new file mode 100644 index 0000000000000000000000000000000000000000..52c74e405e44079555915c753385484060825fe9 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/LightControllable.java @@ -0,0 +1,16 @@ +package model.lightController; + +public interface LightControllable { + public void setDmxValue(int channel, byte value); + public void sendDmxValue(); + public void sendDmxValue(int channel, byte value); + public void activateDmxChannel(int channel); + public void deactivateDmxChannel(int channel); + public void activateGroup(byte groupId); + public void deactivateGroup(byte groupId); + public void activatePreset(int presetId); + public void deactivatePreset(int presetId); + public void clearPreset(int presetId); + public void setPreset(int presetId, byte groupId, int channel, byte value); + public void connectToNodes(); +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/ArtNetController.java b/src/lightControlSoftware/src/model/lightController/artNet/ArtNetController.java new file mode 100644 index 0000000000000000000000000000000000000000..93a496ed937bdc03c97646719f1d5485dee78882 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/ArtNetController.java @@ -0,0 +1,219 @@ +package model.lightController.artNet; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.util.concurrent.atomic.AtomicBoolean; +import com.google.gson.Gson; +import model.lightController.LightControllable; +import model.lightController.artNet.artNetCommands.ActivateGroupCommand; +import model.lightController.artNet.artNetCommands.ActivatePresetCommand; +import model.lightController.artNet.artNetCommands.ClearPresetCommand; +import model.lightController.artNet.artNetCommands.DeactivateGroupCommand; +import model.lightController.artNet.artNetCommands.DeactivatePresetCommand; +import model.lightController.artNet.artNetCommands.SetChannelStateCommand; +import model.lightController.artNet.artNetCommands.SetPresetCommand; +import model.lightController.artNet.artNetNode.ArtNetNode; +import model.lightController.artNet.artNetNode.ArtNetNodeRepository; +import model.lightController.artNet.artNetPakages.ArtCommand; +import model.lightController.artNet.artNetPakages.ArtDataRequest; +import model.lightController.artNet.artNetPakages.ArtDmx; +import model.lightController.artNet.artNetPakages.ArtNetCodeLibrary; +import model.lightController.artNet.artNetPakages.ArtPoll; +import model.lightController.artNet.udpListener.UdpListener; +import model.preset.PresetRepository; + + +public class ArtNetController implements LightControllable { + + private ArtNetNodeRepository artNetNodeRepository; + private UdpListener udpListener; + private PresetRepository presetRepository; + private Thread udpListenerTherad; + private byte[] dmxValues; + private int artNodePort = 6454; + private final AtomicBoolean runningUdpListener = new AtomicBoolean(false); + Gson gson; + + public ArtNetController(PresetRepository presetRepository) { + super(); + this.presetRepository = presetRepository; + this.artNetNodeRepository = new ArtNetNodeRepository(); + this.dmxValues = new byte[100]; + this.gson = new Gson(); + this.udpListener = new UdpListener(this, artNodePort, this.presetRepository, this.runningUdpListener); + + + + + //ArtNetNode artNetNode = new ArtNetNode("GlobalNode", "192.168.178.109", artNodePort); + //ArtNetNode artNetNode = new ArtNetNode("Arduino", "192.168.0.101", artNodePort); + ArtNetNode artNetNode = new ArtNetNode("Enttec", "192.168.0.100", artNodePort); + this.artNetNodeRepository.addNode(artNetNode); + } + + private void sendUdpForEachNode(byte[] udpSendData) { + this.artNetNodeRepository.getNodesMap().forEach((String name, ArtNetNode node) -> { + if(node.getNet() == 0 && node.getSubNet() == 0 && node.getUniverse() == 0 && node.isConnected()) { + try(DatagramSocket socket = new DatagramSocket()) { + InetAddress reciverIP = InetAddress.getByName(node.getIp()); + DatagramPacket outgoingDatagram = new DatagramPacket(udpSendData, udpSendData.length, reciverIP, node.getPort()); + socket.send(outgoingDatagram); + } catch (SocketException e) { + e.printStackTrace(System.err); + } catch (IOException e) { + e.printStackTrace(System.err); + } + } + }); + } + + private void sendArtCommand(ArtCommand artCommand) { + this.sendUdpForEachNode(artCommand.getUdpArray()); + } + + private void sendArtPoll() { + System.out.println("ArtPoll senden."); + byte[] udpSendData = (new ArtPoll()).getUdpArray(); + + this.artNetNodeRepository.getNodesMap().forEach((String name, ArtNetNode node) -> { + if(node.getNet() == 0 && node.getSubNet() == 0 && node.getUniverse() == 0) { + try(DatagramSocket socket = new DatagramSocket()) { + byte[] broadcast = InetAddress.getLocalHost().getAddress(); + System.out.println(InetAddress.getLocalHost()); + broadcast[3] = (byte)255; + InetAddress reciverIP = InetAddress.getByAddress(broadcast); + DatagramPacket outgoingDatagram = new DatagramPacket(udpSendData, udpSendData.length, reciverIP, node.getPort()); + socket.send(outgoingDatagram); + } catch (SocketException e) { + e.printStackTrace(System.err); + } catch (IOException e) { + e.printStackTrace(System.err); + } + } + }); + } + + private void sendDataRequest() { + System.out.println("ArtDataRequest senden."); + ArtDataRequest artDataRequest = new ArtDataRequest(ArtNetCodeLibrary.RequestCodes.DR_PRESET_STATUS.requestCode); + this.sendUdpForEachNode(artDataRequest.getUdpArray()); + } + + @Override + public void setDmxValue(int channel, byte value) + { + //System.out.println(String.format("Channel %d wurde auf %d gesetzt", channel, Byte.toUnsignedInt(value))); + this.dmxValues[channel-1] = value; + } + + @Override + public void sendDmxValue() { + //System.out.println("DMX-Daten werden gesendet."); + byte[] udpSendData = (new ArtDmx(this.dmxValues)).getUdpArray(); + + this.sendUdpForEachNode(udpSendData); + } + + @Override + public void sendDmxValue(int channel, byte value) { + this.dmxValues[channel-1] = value; + sendDmxValue(); + } + + @Override + public void activateDmxChannel(int channel) { + //System.out.println(String.format("Channel %d wurde aktiviert", channel)); + SetChannelStateCommand setChannelStateCommand = new SetChannelStateCommand(channel, true); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_SC.command + "=" + this.gson.toJson(setChannelStateCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void deactivateDmxChannel(int channel) { + //System.out.println(String.format("Channel %d wurde deaktiviert", channel)); + SetChannelStateCommand setChannelStateCommand = new SetChannelStateCommand(channel, false); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_SC.command + "=" + this.gson.toJson(setChannelStateCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void activateGroup(byte groupId) { + //System.out.println(String.format("Gruppe %d wurde aktiviert", Byte.toUnsignedInt(groupId))); + ActivateGroupCommand activateGroupCommand = new ActivateGroupCommand(groupId); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_AG.command + "=" + this.gson.toJson(activateGroupCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void deactivateGroup(byte groupId) { + //System.out.println(String.format("Gruppe %d wurde deaktiviert", Byte.toUnsignedInt(groupId))); + DeactivateGroupCommand deactivateGroupCommand = new DeactivateGroupCommand(groupId); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_DG.command + "=" + this.gson.toJson(deactivateGroupCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void activatePreset(int presetId) { + System.out.println(String.format("Preset %d wurde aktiviert", presetId)); + ActivatePresetCommand activatePresetCommand = new ActivatePresetCommand(presetId); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_AP.command + "=" + this.gson.toJson(activatePresetCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void deactivatePreset(int presetId) { + System.out.println(String.format("Preset %d wurde deaktiviert", presetId)); + DeactivatePresetCommand deactivatePresetCommand = new DeactivatePresetCommand(presetId); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_DP.command + "=" + this.gson.toJson(deactivatePresetCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void clearPreset(int presetId) { + System.out.println(String.format("Preset %d wird gelöscht", presetId)); + ClearPresetCommand clearPresetCommand = new ClearPresetCommand(presetId); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_CP.command + "=" + this.gson.toJson(clearPresetCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void setPreset(int presetId, byte groupId, int channel, byte value) { + System.out.println(String.format("Preset %d wird gesetzt", presetId)); + SetPresetCommand setPresetCommand = new SetPresetCommand(presetId, Byte.toUnsignedInt(groupId), channel, Byte.toUnsignedInt(value)); + String command = ArtNetCodeLibrary.ArtCommands.ART_COM_SP.command + "=" + this.gson.toJson(setPresetCommand); + sendArtCommand(new ArtCommand(command)); + } + + @Override + public void connectToNodes() { + udpListenerTherad = new Thread(this.udpListener); + this.runningUdpListener.set(true); + udpListenerTherad.start(); + this.sendArtPoll(); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + if(!this.artNetNodeRepository.isNodesConnected()) { + this.artNetNodeRepository.getNodesMap().forEach((String name, ArtNetNode node) -> { + if(!node.isConnected()) { + node.setConnectStatus(false); + } + }); + } + this.sendDataRequest(); + } + + public void disconnectNodes() { + this.runningUdpListener.set(false); + } + + public ArtNetNodeRepository getNodeRepository() { + return this.artNetNodeRepository; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ActivateGroupCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ActivateGroupCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..db5da3616062d531df0d1ba8da319cea07b6eee3 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ActivateGroupCommand.java @@ -0,0 +1,9 @@ +package model.lightController.artNet.artNetCommands; + +public class ActivateGroupCommand { + private int groupId; + + public ActivateGroupCommand(int groupId) { + this.groupId = groupId; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ActivatePresetCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ActivatePresetCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..bb51cdb5b059162c717edff5abdbdf1b4ca6c881 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ActivatePresetCommand.java @@ -0,0 +1,9 @@ +package model.lightController.artNet.artNetCommands; + +public class ActivatePresetCommand { + private int presetId; + + public ActivatePresetCommand(int presetId) { + this.presetId = presetId; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ClearPresetCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ClearPresetCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..7508a1e9a96bf37ea1b6348646637e05bd73138d --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/ClearPresetCommand.java @@ -0,0 +1,9 @@ +package model.lightController.artNet.artNetCommands; + +public class ClearPresetCommand { + private int presetId; + + public ClearPresetCommand(int presetId) { + this.presetId = presetId; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/DeactivateGroupCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/DeactivateGroupCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..382ccd7ee7c72a88776f4a52c5c45e78207169bf --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/DeactivateGroupCommand.java @@ -0,0 +1,9 @@ +package model.lightController.artNet.artNetCommands; + +public class DeactivateGroupCommand { + int groupId; + + public DeactivateGroupCommand(int groupId) { + this.groupId = groupId; + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/DeactivatePresetCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/DeactivatePresetCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..88ded60ccb5756f021f23fba3467e850444daf47 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/DeactivatePresetCommand.java @@ -0,0 +1,9 @@ +package model.lightController.artNet.artNetCommands; + +public class DeactivatePresetCommand { + int presetId; + + public DeactivatePresetCommand(int presetId) { + this.presetId = presetId; + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/PresetActivatedCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/PresetActivatedCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..45b22bb5bcdf15a11e5544fabc397ccc49e97fd3 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/PresetActivatedCommand.java @@ -0,0 +1,15 @@ +package model.lightController.artNet.artNetCommands; + +public class PresetActivatedCommand { + private int presetId; + + public PresetActivatedCommand() {} + + public PresetActivatedCommand(int presetId) { + this.presetId = presetId; + } + + public int getPresetId() { + return this.presetId; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/PresetDeactivatedCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/PresetDeactivatedCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..bf1655602bb1531f718e7515a270ba45a16205ca --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/PresetDeactivatedCommand.java @@ -0,0 +1,15 @@ +package model.lightController.artNet.artNetCommands; + +public class PresetDeactivatedCommand { + int presetId; + + public PresetDeactivatedCommand() {} + + public PresetDeactivatedCommand(int presetId) { + this.presetId = presetId; + } + + public int getPresetId() { + return presetId; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/SetChannelStateCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/SetChannelStateCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..04a19b0e14a1a03b7494c04c45b32e60186cc59b --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/SetChannelStateCommand.java @@ -0,0 +1,11 @@ +package model.lightController.artNet.artNetCommands; + +public class SetChannelStateCommand { + int channel; + boolean isActive; + + public SetChannelStateCommand(int channel, boolean isActive) { + this.channel = channel; + this.isActive = isActive; + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/SetPresetCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/SetPresetCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..77ebaf8dc61e0b57951fdeab8c698ee31f52a3ac --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetCommands/SetPresetCommand.java @@ -0,0 +1,15 @@ +package model.lightController.artNet.artNetCommands; + +public class SetPresetCommand { + int presetId; + int groupId; + int channel; + int value; + + public SetPresetCommand(int presetId, int groupId, int channel, int value) { + this.presetId = presetId; + this.groupId = groupId; + this.channel = channel; + this.value = value; + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetNode/ArtNetNode.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetNode/ArtNetNode.java new file mode 100644 index 0000000000000000000000000000000000000000..7cafadacaa55166a9cda04b59839d43b1309f721 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetNode/ArtNetNode.java @@ -0,0 +1,98 @@ +package model.lightController.artNet.artNetNode; + +import java.util.concurrent.atomic.AtomicBoolean; + +import model.generic.PropertyItem; + +public class ArtNetNode extends PropertyItem{ + private String name; + private String ip; + private int port; + private byte net; + private byte subNet; + private byte universe; + private AtomicBoolean connected = new AtomicBoolean(false); + + public ArtNetNode(String name, String ip, int port) { + super(); + this.name = name; + this.ip = ip; + this.port = port; + this.net = (byte)0x00; + this.subNet = (byte)0x00; + this.universe = (byte)0x00; + } + + public ArtNetNode(String name, String ip, int port, byte net, byte subNet, byte universe) { + super(); + this.name = name; + this.ip = ip; + this.port = port; + this.net = net; + this.subNet = subNet; + this.universe = universe; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.propertySupport.firePropertyChange("name", this.name, name); + this.name = name; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.propertySupport.firePropertyChange("ip", this.ip, ip); + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.propertySupport.firePropertyChange("port", this.port, port); + this.port = port; + } + + public byte getNet() { + return net; + } + + public void setNet(byte net) { + this.propertySupport.firePropertyChange("net", this.net, net); + this.net = net; + } + + public byte getSubNet() { + return subNet; + } + + public void setSubNet(byte subNet) { + this.propertySupport.firePropertyChange("subNet", this.subNet, subNet); + this.subNet = subNet; + } + + public byte getUniverse() { + return universe; + } + + public void setUniverse(byte universe) { + this.propertySupport.firePropertyChange("universe", this.universe, universe); + this.universe = universe; + } + + public boolean isConnected() { + return this.connected.get(); + } + + public void setConnectStatus(boolean status) { + this.propertySupport.firePropertyChange("connected", this.connected, status); + this.connected.set(status); + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetNode/ArtNetNodeRepository.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetNode/ArtNetNodeRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..10ea210bf26d98150917a7cd4a0f0246d6e04c25 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetNode/ArtNetNodeRepository.java @@ -0,0 +1,71 @@ +package model.lightController.artNet.artNetNode; + +import java.util.Map; + +import model.generic.PropertyItem; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.HashMap; + +public class ArtNetNodeRepository extends PropertyItem{ + private Map<String, ArtNetNode> nodes; + private boolean nodesConnected = false; + private int numberOfConnectedNodes = 0; + private PropertyChangeListener nodesListener; + + public ArtNetNodeRepository() { + super(); + nodes = new HashMap<>(); + this.nodesListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("connected")) { + if((boolean) event.getNewValue()) { + numberOfConnectedNodes++; + } else { + if(numberOfConnectedNodes >0) { + numberOfConnectedNodes--; + } + } + if(numberOfConnectedNodes == nodes.size()) { + setNodesConnected(true); + } else if(numberOfConnectedNodes == 0) { + setNodesConnected(false); + } + } + } + }; + } + + public void setNodesConnected(boolean connected) { +// if(this.nodesConnected != connected) { + + this.propertySupport.firePropertyChange("nodesConnected", null, connected); + this.nodesConnected = connected; +// } + } + + public void addNode(ArtNetNode artNetNode) { + artNetNode.addPropertyChangeListener(this.nodesListener); + nodes.put(artNetNode.getName(), artNetNode); + this.propertySupport.firePropertyChange("nodes", null, artNetNode); + } + + public void removeNode(ArtNetNode artNetNode) { + this.propertySupport.firePropertyChange("nodes", artNetNode,null); + nodes.remove(artNetNode.getName(), artNetNode); + } + + public boolean isNodesConnected() { + return this.nodesConnected; + } + + public ArtNetNode getNode(String name) { + return this.nodes.get(name); + } + + public Map<String, ArtNetNode> getNodesMap() { + return this.nodes; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtCommand.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..4f077e5251f9ace64ba8216b679b37ca7323f18d --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtCommand.java @@ -0,0 +1,108 @@ +package model.lightController.artNet.artNetPakages; + +import java.nio.ByteBuffer; + +public class ArtCommand { + private String id = "Art-Net" + (char)0x00; + private short opCode = ArtNetCodeLibrary.OpCodes.OP_COMMAND.opCode; + private byte protVerHi = 0x00; + private byte protVerLo = 0x0e; // Version 14; + private byte estaManHi = 0x00; + private byte estaManLo = 0x00; + private short length = 0x0000; + private String data; + + public ArtCommand(String data) { + this.length = (short) data.length(); + this.data = data; + } + + public ArtCommand(byte[] udpArray) { + byte[] lengthArray = new byte[2]; + char[] data = new char[udpArray.length - 16]; + + // protocoll version + this.protVerHi = udpArray[10]; + this.protVerLo = udpArray[11]; + + // esta manifactur + this.estaManHi = udpArray[12]; + this.estaManLo = udpArray[13]; + + // length + lengthArray[0] = udpArray[14]; + lengthArray[1] = udpArray[15]; + this.length = ByteBuffer.wrap(lengthArray).getShort(); + + for(int i=0; i < this.length; i++) + { + data[i] = (char)udpArray[16+i]; + } + this.data = String.copyValueOf(data); + } + + public byte[] getUdpArray() { + byte[] udpArray = new byte[16 + this.data.length()]; + byte[] opCodeArray = ByteBuffer.allocate(2).putShort(this.opCode).array(); + byte[] lengthArray = ByteBuffer.allocate(2).putShort(this.length).array(); + + // id + for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); + } + + // op code + udpArray[8] = opCodeArray[1]; + udpArray[9] = opCodeArray[0]; + + // protocoll version + udpArray[10] = this.protVerHi; + udpArray[11] = this.protVerLo; + + // esta manifactur + udpArray[12] = this.estaManHi; + udpArray[13] = this.estaManLo; + + // length + udpArray[14] = lengthArray[0]; + udpArray[15] = lengthArray[1]; + + for(int i=0; i < this.length; i++) { + udpArray[16+i] = this.data.getBytes()[i]; + } + + return udpArray; + } + + public String getId() { + return id; + } + + public short getOpCode() { + return opCode; + } + + public byte getProtVerHi() { + return protVerHi; + } + + public byte getProtVerLo() { + return protVerLo; + } + + public byte getEstaManHi() { + return estaManHi; + } + + public byte getEstaManLo() { + return estaManLo; + } + + public short getLength() { + return length; + } + + public String getData() { + return data; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDataReply.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDataReply.java new file mode 100644 index 0000000000000000000000000000000000000000..e7d388ae1e537a5d5a70e2d631f5d7c7a5bf8254 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDataReply.java @@ -0,0 +1,142 @@ +package model.lightController.artNet.artNetPakages; + +import java.nio.ByteBuffer; + +public class ArtDataReply { + private String id = "Art-Net" + (char)0x00; + private short opCode = ArtNetCodeLibrary.OpCodes.OP_DATA_REPLY.opCode; + private byte protVerHi = 0x00; + private byte protVerLo = 0x0e; // Version 14; + private byte estaManHi = 0x00; + private byte estaManLo = 0x00; + private byte oemHi = (byte)0xff; + private byte oemLo = (byte)0xff; + private short requestCode = 0x0000; + private short payLength = 0x0000; + private byte[] payLoad; + + public ArtDataReply(String payLoad) { + this.payLoad = payLoad.getBytes(); + } + + public ArtDataReply(byte[] udpArray) { + byte[] requestCodeArray = new byte[2]; + byte[] payLengthArray = new byte[2]; + + // protocoll version + this.protVerHi = udpArray[10]; + this.protVerLo = udpArray[11]; + + // esta manifactur + this.estaManHi = udpArray[12]; + this.estaManLo = udpArray[13]; + + // oem + this.oemHi = udpArray[14]; + this.oemLo = udpArray[15]; + + // request code + requestCodeArray[1] = udpArray[16]; + requestCodeArray[0] = udpArray[17]; + this.requestCode = ByteBuffer.wrap(requestCodeArray).getShort(); + + // length + payLengthArray[0] = udpArray[18]; + payLengthArray[1] = udpArray[19]; + this.payLength = ByteBuffer.wrap(payLengthArray).getShort(); + + // payload + byte[] payLoadArray = new byte[this.payLength]; + for(int i=0; i < this.payLength; i++) { + payLoadArray[i] = udpArray[20+i]; + } + this.payLoad = payLoadArray; + } + + public byte[] getUdpArray() { + byte[] udpArray = new byte[20 + this.payLength]; + byte[] opCodeArray = ByteBuffer.allocate(2).putShort(this.opCode).array(); + byte[] requestCodeArray = ByteBuffer.allocate(2).putShort(this.requestCode).array(); + byte[] payLengthArray = ByteBuffer.allocate(2).putShort(this.payLength).array(); + + // id + for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); + } + + // op code + udpArray[8] = opCodeArray[1]; + udpArray[9] = opCodeArray[0]; + + // protocoll version + udpArray[10] = this.protVerHi; + udpArray[11] = this.protVerLo; + + // esta manifactur + udpArray[12] = this.estaManHi; + udpArray[13] = this.estaManLo; + + // oem + udpArray[14] = this.oemHi; + udpArray[15] = this.oemLo; + + // request code + udpArray[16] = requestCodeArray[1]; + udpArray[17] = requestCodeArray[0]; + + // length + udpArray[18] = payLengthArray[1]; + udpArray[19] = payLengthArray[0]; + + // payload + for(int i=0; i < this.payLength; i++) { + udpArray[20+i] = this.payLoad[i]; + } + + return udpArray; + } + + public String getId() { + return id; + } + + public short getOpCode() { + return opCode; + } + + public byte getProtVerHi() { + return protVerHi; + } + + public byte getProtVerLo() { + return protVerLo; + } + + public byte getEstaManHi() { + return estaManHi; + } + + public byte getEstaManLo() { + return estaManLo; + } + + public byte getOemHi() { + return oemHi; + } + + public byte getOemLo() { + return oemLo; + } + + public short getRequestCode() { + return requestCode; + } + + public short getPayLength() { + return payLength; + } + + public byte[] getPayLoad() { + return payLoad; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDataRequest.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDataRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..cb3642a19a685d41e12a7ace21152d1ffba927ad --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDataRequest.java @@ -0,0 +1,109 @@ +package model.lightController.artNet.artNetPakages; + +import java.nio.ByteBuffer; + +public class ArtDataRequest { + private String id = "Art-Net" + (char)0x00; + private short opCode = ArtNetCodeLibrary.OpCodes.OP_DATA_REQUEST.opCode; + private byte protVerHi = 0x00; + private byte protVerLo = 0x0e; // Version 14; + private byte estaManHi = 0x00; + private byte estaManLo = 0x00; + private byte oemHi = (byte)0xff; + private byte oemLo = (byte)0xff; + private short requestCode = 0x0000; + + public ArtDataRequest(short requestCode) { + this.requestCode = requestCode; + } + + public ArtDataRequest(byte[] udpArray) { + byte[] requestCodeArray = new byte[2]; + + // protocoll version + this.protVerHi = udpArray[10]; + this.protVerLo = udpArray[11]; + + // esta manifactur + this.estaManHi = udpArray[12]; + this.estaManLo = udpArray[13]; + + // oem + this.oemHi = udpArray[14]; + this.oemLo = udpArray[15]; + + // request code + requestCodeArray[0] = udpArray[16]; + requestCodeArray[1] = udpArray[17]; + this.requestCode = ByteBuffer.wrap(requestCodeArray).getShort(); + } + + public byte[] getUdpArray() { + byte[] udpArray = new byte[18]; + byte[] opCodeArray = ByteBuffer.allocate(2).putShort(this.opCode).array(); + byte[] requestCodeArray = ByteBuffer.allocate(2).putShort(this.requestCode).array(); + + // id + for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); + } + + // op code + udpArray[8] = opCodeArray[1]; + udpArray[9] = opCodeArray[0]; + + // protocoll version + udpArray[10] = this.protVerHi; + udpArray[11] = this.protVerLo; + + // esta manifactur + udpArray[12] = this.estaManHi; + udpArray[13] = this.estaManLo; + + // oem + udpArray[14] = this.oemHi; + udpArray[15] = this.oemLo; + + // request code + udpArray[16] = requestCodeArray[0]; + udpArray[17] = requestCodeArray[1]; + + return udpArray; + } + + public String getId() { + return id; + } + + public short getOpCode() { + return opCode; + } + + public byte getProtVerHi() { + return protVerHi; + } + + public byte getProtVerLo() { + return protVerLo; + } + + public byte getEstaManHi() { + return estaManHi; + } + + public byte getEstaManLo() { + return estaManLo; + } + + public byte getOemHi() { + return oemHi; + } + + public byte getOemLo() { + return oemLo; + } + + public short getRequestCode() { + return requestCode; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDmx.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDmx.java new file mode 100644 index 0000000000000000000000000000000000000000..2cacffed5de6c169c670cb4f186e6de796783a42 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtDmx.java @@ -0,0 +1,74 @@ +package model.lightController.artNet.artNetPakages; + +import java.nio.ByteBuffer; + +public class ArtDmx { + private String id = "Art-Net" + ((char)0x00); + private short opCode = ArtNetCodeLibrary.OpCodes.OP_DMX.opCode; + private byte protVerHi = 0x00; + private byte protVerLo = 0x10; // Version 14; + private byte sequence = 0x00; + private byte physical = 0x00; + private byte subUni = 0x00; + private byte net = 0x00; + private short length = 0x0200; + private byte[] data; + + public ArtDmx(byte[] data) { + this.length = (short)data.length; + this.data = data; + } + + public ArtDmx(byte[] data, byte net, byte subNet, byte universe) { + this.net = net; + + byte firstPart = (byte) (subNet & 0b0001_1111); + byte secondPart = (byte) (universe & 0b0000_0111); + this.subUni = (byte) ((firstPart << 3) | secondPart); + + this.length = (short)data.length; + this.data = data; + } + + public byte[] getUdpArray() { + byte[] udpArray = new byte[18 + this.length]; + byte[] opCodeArray = ByteBuffer.allocate(2).putShort(this.opCode).array(); + byte[] lengthArray = ByteBuffer.allocate(2).putShort(this.length).array(); + + // id + for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); + } + + // op code + udpArray[8] = opCodeArray[1]; + udpArray[9] = opCodeArray[0]; + + // protocoll version + udpArray[10] = this.protVerHi; + udpArray[11] = this.protVerLo; + + // sequence + udpArray[12] = this.sequence; + + // physical + udpArray[13] = this.physical; + + // sub-net and universe + udpArray[14] = this.subUni; + + // net + udpArray[15] = this.net; + + // length + udpArray[16] = lengthArray[0]; + udpArray[17] = lengthArray[1]; + + for(int i = 0; i < this.length; i++) { + + udpArray[18 + i] = this.data[i]; + } + + return udpArray; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtNetCodeLibrary.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtNetCodeLibrary.java new file mode 100644 index 0000000000000000000000000000000000000000..7e8427bb5794be663c9fee7ed6744d5985a56e7a --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtNetCodeLibrary.java @@ -0,0 +1,53 @@ +package model.lightController.artNet.artNetPakages; + +public class ArtNetCodeLibrary { + public static enum OpCodes { + OP_POLL((short)0x2000), + OP_POLL_REPLY((short)0x2100), + OP_COMMAND((short)0x2400), + OP_DATA_REQUEST((short)0x2700), + OP_DATA_REPLY((short)0x2800), + OP_DMX((short)0x5000); + + public final short opCode; + + private OpCodes(short opCode) { + this.opCode = opCode; + } + } + + public static enum RequestCodes { + DR_POLL ((short)0x0000), + DR_URL_PRODUCT ((short)0x0001), + DR_URL_USER_GUIDE ((short)0x0002), + DR_URL_SUPPORT ((short)0x0003), + DR_URL_PERS_UDR ((short)0x0004), + DR_URL_PERS_GDTF ((short)0x0005), + DR_PRESET_STATUS ((short)0x8000); + + public final short requestCode; + + private RequestCodes(short requestCode) { + this.requestCode = requestCode; + } + } + + public static enum ArtCommands { + ART_COM_AP("activatePreset"), + ART_COM_DP("deactivatePreset"), + ART_COM_CP("clearPreset"), + ART_COM_SP("setPreset"), + ART_COM_SC("setChannelState"), + ART_COM_AG("activateGroup"), + ART_COM_DG("deactivateGroup"), + ART_COM_PA("presetActivated"), + ART_COM_PD("presetDeactivated"); + + public final String command; + + private ArtCommands(String command) { + this.command = command; + } + } + +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtPoll.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtPoll.java new file mode 100644 index 0000000000000000000000000000000000000000..7f08eb5adc447b3248357da3bc39f9a3d7edd9ba --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtPoll.java @@ -0,0 +1,62 @@ +package model.lightController.artNet.artNetPakages; + +import java.nio.ByteBuffer; + +public class ArtPoll { + private String id = "Art-Net" + (char)0x00; + private short opCode = ArtNetCodeLibrary.OpCodes.OP_POLL.opCode; + private byte protVerHi = 0x00; + private byte protVerLo = 0x0E; // Version 14 + private byte flags = 0x00; + private byte diagPriority = 0x00; + private byte targetPortAddressTopHi = 0x00; + private byte targetPortAddressTopLo = 0x00; + private byte targetPortAddressBottomHi = 0x00; + private byte targetPortAddressBottomLo = 0x00; + private byte estaManHi = 0x00; + private byte estaManLo = 0x00; + private byte oemHi = (byte)0xff; + private byte oemLo = (byte)0xff; + + public ArtPoll() {} + + public byte[] getUdpArray() { + byte[] udpArray = new byte[22]; + byte[] opCodeArray = ByteBuffer.allocate(2).putShort(this.opCode).array(); + + // id + for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); + } + + // op code + udpArray[8] = opCodeArray[1]; + udpArray[9] = opCodeArray[0]; + + // protocoll version + udpArray[10] = this.protVerHi; + udpArray[11] = this.protVerLo; + + // flag + udpArray[12] = this.flags; + + // diagonstic prio + udpArray[13] = this.diagPriority; + + // target port + udpArray[14] = this.targetPortAddressTopHi; + udpArray[15] = this.targetPortAddressTopLo; + udpArray[16] = this.targetPortAddressBottomHi; + udpArray[17] = this.targetPortAddressBottomLo; + + // esta manifacture + udpArray[18] = this.estaManHi; + udpArray[19] = this.estaManLo; + + // oem + udpArray[20] = this.oemHi; + udpArray[21] = this.oemLo; + + return udpArray; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtPollReply.java b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtPollReply.java new file mode 100644 index 0000000000000000000000000000000000000000..23f399cedbbceb61afe06724890e127274430d69 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/artNetPakages/ArtPollReply.java @@ -0,0 +1,543 @@ +package model.lightController.artNet.artNetPakages; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; + +public class ArtPollReply { + private String id = "Art-Net" + (char)0x00; + private short opCode = ArtNetCodeLibrary.OpCodes.OP_POLL_REPLY.opCode; + private byte ipAddress[] = {0x00, 0x00, 0x00, 0x00}; + private short port = 0x1936; + private byte versInfoH = 0x00; + private byte versInfoL = 0x01; + private byte netSwitch = 0x00; + private byte subSwitch = 0x00; + private byte oemHi = (byte)0xff; + private byte oemLo = (byte)0xff; + private byte ubeaVersion = 0x00; + private byte status1 = 0x00; + private byte estaManLo = 0x00; + private byte estaManHi = 0x00; + private byte portName[] = {'K', 'I', 'W', 'I', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + private byte longName[] = new byte[64]; + private byte nodeReport[] = new byte[64]; + private byte numPortsHi = 0x00; + private byte numPortsLo = 0x01; + private byte portTypes[] = {0x00, 0x00, 0x00, 0x00}; + private byte goodInput[] = {0x04, 0x04, 0x04, 0x04}; + private byte goodOutputA [] = {0x00, 0x00, 0x00, 0x00}; + private byte swIn[] = {0x00, 0x00, 0x00, 0x00}; + private byte swOut[] = {0x00, 0x00, 0x00, 0x00}; + private byte acnPriority = 0x00; + private byte swMacro = 0x00; + private byte swRemote = 0x00; + private byte style = 0x00; + private byte mac[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + private byte bindIp[] = {0x00, 0x00, 0x00, 0x00}; + private byte bindIndex = 0x00; + private byte status2 = 0x00; + private byte goodOutputB[] = {0x00, 0x00, 0x00, 0x00}; + private byte status3 = 0x00; + private byte defaulRespUID[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + private byte userHi = 0x00; + private byte userLo = 0x00; + private byte refreshRateHi = 0x00; + private byte refreshRateLo = 0x2C; + + public ArtPollReply() { + try { + InetAddress localHost = InetAddress.getLocalHost(); + this.ipAddress = localHost.getAddress(); + this.mac = NetworkInterface.getByInetAddress(localHost).getHardwareAddress(); + } catch (UnknownHostException | SocketException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + byte[] longName = "KIWI (is a) Illumination Weeny Interface".getBytes(); + for(int i = 0; i < longName.length; i++) { + this.longName[i] = longName[i]; + } + } + + public ArtPollReply(byte[] udpArray) { + byte[] portArray = new byte[2]; + + if(udpArray.length >= 207) { + + // node ip + for(int i= 0; i < 4; i++) + { + this.ipAddress[i] = udpArray[10+i]; + } + + // port + portArray[1] = udpArray[14]; + portArray[0] = udpArray[15]; + this.port = ByteBuffer.wrap(portArray).getShort(); + + // version info + this.versInfoH = udpArray[16]; + this.versInfoL = udpArray[17]; + + // net address + this.netSwitch = udpArray[18]; + + // sub net address + this.subSwitch = udpArray[19]; + + // oem + this.oemHi = udpArray[20]; + this.oemLo = udpArray[21]; + + // ubea version + this.ubeaVersion = udpArray[22]; + + // status + this.status1 = udpArray[23]; + + // esta + this.estaManLo = udpArray[24]; + this.estaManHi = udpArray[25]; + + // port name + for (int i = 0; i < 18; i++) + { + this.portName[i] = udpArray[26+i]; + } + + // long name + for (int i = 0; i < 64; i++) + { + this.longName[i] = udpArray[44+i]; + } + + // node report + for (int i = 0; i < 64; i++) + { + this.nodeReport[i] = udpArray[108+i]; + } + + // number of ports + this.numPortsHi = udpArray[172]; + this.numPortsLo = udpArray[173]; + + // port type + for (int i = 0; i < 4; i++) + { + this.portTypes[i] = udpArray[174+i]; + } + + // good inputs + for (int i = 0; i < 4; i++) + { + this.goodInput[i] = udpArray[178+i]; + } + + // good output A + for (int i = 0; i < 4; i++) + { + this.goodOutputA[i] = udpArray[182+i]; + } + + // sw in + for (int i = 0; i < 4; i++) + { + this.swIn[i] = udpArray[186+i]; + } + + // sw out + for (int i = 0; i < 4; i++) + { + this.swOut[i] = udpArray[190+i]; + } + + // prio acn + this.acnPriority = udpArray[194]; + + // sw macro + this.swMacro = udpArray[195]; + + // sw remote + this.swRemote = udpArray[196]; + + // style + this.style = udpArray[200]; + + // mac address + for (int i = 0; i < 6; i++) + { + this.mac[i] = udpArray[201+i]; + } + } + if(udpArray.length >= 208) { + // bind ip + for (int i = 0; i < 4; i++) { + this.bindIp[i] = udpArray[207+i]; + } + } + if(udpArray.length >= 212) { + // bind index + this.bindIndex = udpArray[211]; + } + if(udpArray.length >= 213) { + // status 2 + this.status2 = udpArray[212]; + } + if(udpArray.length >= 214) { + // good output b + for (int i = 0; i < 4; i++) + { + this.goodOutputB[i] = udpArray[213+i]; + } + } + if(udpArray.length >= 218) { + // status 3 + this.status3 = udpArray[217]; + } + if(udpArray.length >= 219) { + // default responder uid + for (int i = 0; i < 6; i++) + { + this.defaulRespUID[i] = udpArray[218+i]; + } + } + if(udpArray.length >= 225) { + // user data + this.userHi = udpArray[224]; + this.userLo = udpArray[225]; + } + if(udpArray.length >= 227) { + // user data + this.refreshRateHi = udpArray[226]; + this.refreshRateLo = udpArray[227]; + } + } + + public byte[] getUdpArray() { + byte[] udpArray = new byte[236]; + byte[] opCodeArray = ByteBuffer.allocate(2).putShort(this.opCode).array(); + byte[] portArray = ByteBuffer.allocate(2).putShort(this.port).array(); + + // id + for(int i = 0; i < 8; i++) { + udpArray[i] = (byte)this.id.charAt(i); + } + + // op code + udpArray[8] = opCodeArray[1]; + udpArray[9] = opCodeArray[0]; + + // node ip + for(int i= 0; i < 4; i++) + { + udpArray[10+i] = this.ipAddress[i]; + } + + // port + udpArray[14] = portArray[1]; + udpArray[15] = portArray[0]; + + // version info + udpArray[16] = this.versInfoH; + udpArray[17] = this.versInfoL; + + // net address + udpArray[18] = this.netSwitch; + + // sub net address + udpArray[19] = this.subSwitch; + + // oem + udpArray[20] = this.oemHi; + udpArray[21] = this.oemLo; + + // ubea version + udpArray[22] = this.ubeaVersion; + + // status + udpArray[23] = this.status1; + + // esta + udpArray[24] = this.estaManLo; + udpArray[25] = this.estaManHi; + + // port name + for (int i = 0; i < 18; i++) + { + udpArray[26+i] = this.portName[i]; + } + + // long name + for (int i = 0; i < 64; i++) + { + udpArray[44+i] = this.longName[i]; + } + + // node report + for (int i = 0; i < 64; i++) + { + udpArray[108+i] = this.nodeReport[i]; + } + + // number of ports + udpArray[172] = this.numPortsHi; + udpArray[173] = this.numPortsLo; + + // port type + for (int i = 0; i < 4; i++) + { + udpArray[174+i] = this.portTypes[i]; + } + + // good inputs + for (int i = 0; i < 4; i++) + { + udpArray[178+i] = this.goodInput[i]; + } + + // good output A + for (int i = 0; i < 4; i++) + { + udpArray[182+i] = this.goodOutputA[i]; + } + + // sw in + for (int i = 0; i < 4; i++) + { + udpArray[186+i] = this.swIn[i]; + } + + // sw out + for (int i = 0; i < 4; i++) + { + udpArray[190+i] = this.swOut[i]; + } + + // prio acn + udpArray[194] = this.acnPriority; + + // sw macro + udpArray[195] = this.swMacro; + + // sw remote + udpArray[196] = this.swRemote; + + // spare + for (int i = 0; i < 3; i++) + { + udpArray[197+i] = 0x00; + } + + // style + udpArray[200] = this.style; + + // mac address + for (int i = 0; i < 6; i++) + { + udpArray[201+i] = this.mac[i]; + } + + // bind ip + for (int i = 0; i < 4; i++) + { + udpArray[207+i] = this.bindIp[i]; + } + + // bind index + udpArray[211] = this.bindIndex; + + // status 2 + udpArray[212] = this.status2; + + // good output b + for (int i = 0; i < 4; i++) + { + udpArray[213+i] = this.goodOutputB[i]; + } + + // status 3 + udpArray[217] = this.status3; + + // default responder uid + for (int i = 0; i < 6; i++) + { + udpArray[218+i] = this.defaulRespUID[i]; + } + + // user data + udpArray[224] = this.userHi; + udpArray[225] = this.userLo; + + // user data + udpArray[226] = this.refreshRateHi; + udpArray[227] = this.refreshRateLo; + + // filler + for (int i = 0; i < 8; i++) + { + udpArray[228+i] = 0x00; + } + + return udpArray; + } + + public String getId() { + return id; + } + + public short getOpCode() { + return opCode; + } + + public byte[] getIpAddress() { + return ipAddress; + } + + public short getPort() { + return port; + } + + public byte getVersInfoH() { + return versInfoH; + } + + public byte getVersInfoL() { + return versInfoL; + } + + public byte getNetSwitch() { + return netSwitch; + } + + public byte getSubSwitch() { + return subSwitch; + } + + public byte getOemHi() { + return oemHi; + } + + public byte getOemLo() { + return oemLo; + } + + public byte getUbeaVersion() { + return ubeaVersion; + } + + public byte getStatus1() { + return status1; + } + + public byte getEstaManLo() { + return estaManLo; + } + + public byte getEstaManHi() { + return estaManHi; + } + + public byte[] getPortName() { + return portName; + } + + public byte[] getLongName() { + return longName; + } + + public byte[] getNodeReport() { + return nodeReport; + } + + public byte getNumPortsHi() { + return numPortsHi; + } + + public byte getNumPortsLo() { + return numPortsLo; + } + + public byte[] getPortTypes() { + return portTypes; + } + + public byte[] getGoodInput() { + return goodInput; + } + + public byte[] getGoodOutputA() { + return goodOutputA; + } + + public byte[] getSwIn() { + return swIn; + } + + public byte[] getSwOut() { + return swOut; + } + + public byte getAcnPriority() { + return acnPriority; + } + + public byte getSwMacro() { + return swMacro; + } + + public byte getSwRemote() { + return swRemote; + } + + public byte getStyle() { + return style; + } + + public byte[] getMac() { + return mac; + } + + public byte[] getBindIp() { + return bindIp; + } + + public byte getBindIndex() { + return bindIndex; + } + + public byte getStatus2() { + return status2; + } + + public byte[] getGoodOutputB() { + return goodOutputB; + } + + public byte getStatus3() { + return status3; + } + + public byte[] getDefaulRespUID() { + return defaulRespUID; + } + + public byte getUserHi() { + return userHi; + } + + public byte getUserLo() { + return userLo; + } + + public byte getRefreshRateHi() { + return refreshRateHi; + } + + public byte getRefreshRateLo() { + return refreshRateLo; + } +} diff --git a/src/lightControlSoftware/src/model/lightController/artNet/udpListener/UdpListener.java b/src/lightControlSoftware/src/model/lightController/artNet/udpListener/UdpListener.java new file mode 100644 index 0000000000000000000000000000000000000000..6728b5e5f2b0a1ca35e6b25a75956f08b4a528a5 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightController/artNet/udpListener/UdpListener.java @@ -0,0 +1,159 @@ +package model.lightController.artNet.udpListener; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicBoolean; +import com.google.gson.Gson; + +import model.lightController.artNet.ArtNetController; +import model.lightController.artNet.artNetCommands.PresetActivatedCommand; +import model.lightController.artNet.artNetCommands.PresetDeactivatedCommand; +import model.lightController.artNet.artNetNode.ArtNetNode; +import model.lightController.artNet.artNetPakages.ArtCommand; +import model.lightController.artNet.artNetPakages.ArtDataReply; +import model.lightController.artNet.artNetPakages.ArtNetCodeLibrary; +import model.lightController.artNet.artNetPakages.ArtPollReply; +import model.preset.PresetRepository; + +public class UdpListener implements Runnable{ + + private ArtNetController artNetController; + private PresetRepository presetRepository; + private int port = 6454; + private byte[] opCodeArray = new byte[2]; + private short opCode; + byte[] incomingData; + AtomicBoolean running; + Gson gson; + + public UdpListener(ArtNetController artNetController, int port, PresetRepository presetRepository, AtomicBoolean running) { + this.artNetController = artNetController; + this.presetRepository = presetRepository; + this.running = running; + incomingData = new byte[550]; + this.gson = new Gson(); + } + + private boolean checkIfArtNetPakage(byte[] incomingData) { + boolean isArtNet = true; + byte[] artNetString = ("Art-Net" + (char)0x00).getBytes(); + + for(int i = 0; i<8; i++) { + if(artNetString[i] != incomingData[i]) { + isArtNet = false; + } + } + return isArtNet; + } + + private String convertIp(byte[] ip) { + String ipString = ""; + for(int i = 0; i<3; i++) { + ipString += Byte.toUnsignedInt(ip[i]) + "."; + } + ipString += Byte.toUnsignedInt(ip[3]); + return ipString; + } + + private void sendArtPollReply(InetAddress reciverIP) { + byte[] udpSendData = (new ArtPollReply()).getUdpArray(); + + try(DatagramSocket socket = new DatagramSocket()) { + DatagramPacket outgoingDatagram = new DatagramPacket(udpSendData, udpSendData.length, reciverIP, this.port); + socket.send(outgoingDatagram); + } catch (SocketException e) { + e.printStackTrace(System.err); + } catch (IOException e) { + e.printStackTrace(System.err); + } + } + + private void processArtPollReply() { + System.out.println("ArtPollReply empfangen"); + ArtPollReply artPollReply = new ArtPollReply(incomingData); + artNetController.getNodeRepository().getNodesMap().forEach((String name, ArtNetNode node) -> { + if(convertIp(artPollReply.getIpAddress()).equals(node.getIp())) { + node.setConnectStatus(true); + } + }); + } + + private void processArtCommand() { + ArtCommand artCommand = new ArtCommand(incomingData); + String commandsString = artCommand.getData(); + String[] commands = commandsString.split("&"); + for(String commandString : commands) { + String command = commandString.split("=")[0]; + String commandJSON = commandString.split("=")[1].trim(); + + if(command.equals(ArtNetCodeLibrary.ArtCommands.ART_COM_PA.command)) { + PresetActivatedCommand presetActivatedCommand = this.gson.fromJson(commandJSON, PresetActivatedCommand.class); + presetRepository.getPreset(presetActivatedCommand.getPresetId()).activate(); + + } else if(command.equals(ArtNetCodeLibrary.ArtCommands.ART_COM_PD.command)) { + PresetDeactivatedCommand presetDeactivatedCommand = this.gson.fromJson(commandJSON, PresetDeactivatedCommand.class); + presetRepository.getPreset(presetDeactivatedCommand.getPresetId()).deactivate(); + } + } + } + + private void processArtDataReply() { + ArtDataReply artDataReply = new ArtDataReply(incomingData); + if(artDataReply.getRequestCode() == ArtNetCodeLibrary.RequestCodes.DR_PRESET_STATUS.requestCode) { + for(int i = 0; i < (int)artDataReply.getPayLength(); i++) { + if(artDataReply.getPayLoad()[i] == 1) { + presetRepository.getPreset(i).activate(); + } + } + } + } + + @Override + public void run() { + + try(DatagramSocket socket = new DatagramSocket(this.port)) { + socket.setSoTimeout(1000); + while(this.running.get()) { + try { + DatagramPacket incomingDatagram = new DatagramPacket(this.incomingData, this.incomingData.length); + socket.receive(incomingDatagram); + this.incomingData = incomingDatagram.getData(); + + if(checkIfArtNetPakage(this.incomingData)) { + opCodeArray[0] = this.incomingData[9]; + opCodeArray[1] = this.incomingData[8]; + this.opCode = ByteBuffer.wrap(opCodeArray).getShort(); + if(this.opCode == ArtNetCodeLibrary.OpCodes.OP_POLL.opCode) { + //System.out.println("Art Poll empfangen."); + this.sendArtPollReply(incomingDatagram.getAddress()); + }else if(this.opCode == ArtNetCodeLibrary.OpCodes.OP_POLL_REPLY.opCode) { + //System.out.println("Art Poll Reply empfangen."); + this.processArtPollReply(); + } else if(this.opCode == ArtNetCodeLibrary.OpCodes.OP_COMMAND.opCode) { + System.out.println("Art Command empfangen."); + this.processArtCommand(); + } else if(this.opCode == ArtNetCodeLibrary.OpCodes.OP_DATA_REPLY.opCode) { + //System.out.println("Art Data Reply empfangen."); + this.processArtDataReply(); + } + } + } catch (SocketTimeoutException e) {} + } + socket.close(); + } catch (SocketException e) { + e.printStackTrace(System.err); + } catch (IOException e) { + e.printStackTrace(System.err); + } finally { + artNetController.getNodeRepository().getNodesMap().forEach((String name, ArtNetNode node) -> { + node.setConnectStatus(false); + }); + } + } + +} diff --git a/src/lightControlSoftware/src/model/lightingScene/LightingScene.java b/src/lightControlSoftware/src/model/lightingScene/LightingScene.java new file mode 100644 index 0000000000000000000000000000000000000000..cc3418c8336cd4f571d48c9c5a7da8b9f6c04835 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightingScene/LightingScene.java @@ -0,0 +1,12 @@ +package model.lightingScene; + +public interface LightingScene { + public static enum LightingSceneType + { + LIGHTING_MOOD, + COMPOSITION + }; + public LightingSceneType getLightingSceneType(); + public void activate(); + public void deactivate(); +} diff --git a/src/lightControlSoftware/src/model/lightingScene/composition/Composition.java b/src/lightControlSoftware/src/model/lightingScene/composition/Composition.java new file mode 100644 index 0000000000000000000000000000000000000000..65a1dfcdd056cbc9b9a28ab204611671a12d35d2 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightingScene/composition/Composition.java @@ -0,0 +1,72 @@ +package model.lightingScene.composition; + +import java.util.Map; + +import model.fixture.DmxValues; +import model.generic.PropertyItem; +import model.lightingScene.LightingScene; + +import java.util.HashMap; + +public class Composition extends PropertyItem implements LightingScene{ + private String name; + private boolean isActive; + private Map<String, DmxValues> fixtureValues; + + public Composition(String name) { + super(); + this.name = name; + this.isActive = false; + this.fixtureValues = new HashMap<>(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + String nameOld = this.name; + this.name = name; + propertySupport.firePropertyChange("name", nameOld, name); + } + + public boolean isActive() { + return this.isActive; + } + + public void setDmxValuesForFixture(String fixtureName, DmxValues values) { + propertySupport.firePropertyChange("setFixtureValues", fixtureName, values); + fixtureValues.put(fixtureName, values); + } + + public void removeFixtureFromComposition(String fixtureName) { + propertySupport.firePropertyChange("removeFixtureValues", fixtureName, null); + fixtureValues.remove(fixtureName); + } + + public DmxValues getDmxValuesForFixture(String fixtureName) { + return fixtureValues.get(fixtureName); + } + + @Override + public void activate() { + boolean activeOld = this.isActive; + this.isActive = true; + propertySupport.firePropertyChange("isActive", activeOld, true); + } + + @Override + public void deactivate() { + boolean activeOld = this.isActive; + this.isActive = false; + propertySupport.firePropertyChange("isActive", activeOld, false); + } + + public LightingSceneType getLightingSceneType() { + return LightingSceneType.COMPOSITION; + } + + public Map<String, DmxValues> getFixtureValues() { + return this.fixtureValues; + } +} diff --git a/src/lightControlSoftware/src/model/lightingScene/composition/CompositionRepository.java b/src/lightControlSoftware/src/model/lightingScene/composition/CompositionRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..3e0edf8eec51f740b856bf99502dc9786606bcc0 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightingScene/composition/CompositionRepository.java @@ -0,0 +1,33 @@ +package model.lightingScene.composition; + +import java.util.Map; + +import model.generic.PropertyItem; + +import java.util.HashMap; + +public class CompositionRepository extends PropertyItem { + private Map<String, Composition> compositions; + + public CompositionRepository() { + this.compositions = new HashMap<>(); + } + + public void addComposition(Composition composition) { + this.compositions.put(composition.getName(), composition); + this.propertySupport.firePropertyChange("compositions", null, composition); + } + + public Composition getComposition(String name) { + return compositions.get(name); + } + + public void removeComposition(String name) { + this.propertySupport.firePropertyChange("compositions", this.compositions.get(name), null); + this.compositions.remove(name); + } + + public Map<String, Composition> getCompositionMap() { + return this.compositions; + } +} diff --git a/src/lightControlSoftware/src/model/lightingScene/lightingMood/LightingMood.java b/src/lightControlSoftware/src/model/lightingScene/lightingMood/LightingMood.java new file mode 100644 index 0000000000000000000000000000000000000000..3f031195bc25e261f282afa982fdbce54a1f70f6 --- /dev/null +++ b/src/lightControlSoftware/src/model/lightingScene/lightingMood/LightingMood.java @@ -0,0 +1,60 @@ +package model.lightingScene.lightingMood; + +import model.fixture.DmxValues; +import model.generic.PropertyItem; +import model.lightingScene.LightingScene; + +public class LightingMood extends PropertyItem implements LightingScene{ + private String name; + private boolean isActive; + private DmxValues dmxValues; + + public LightingMood(String name) { + super(); + this.name = name; + this.isActive = false; + this.dmxValues = new DmxValues(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + propertySupport.firePropertyChange("name", this.name, name); + this.name = name; + } + + public boolean isActive() { + return this.isActive; + } + + public DmxValues getDmxValues() { + return this.dmxValues; + } + + public void setDmxValues(DmxValues dmxValues) { + propertySupport.firePropertyChange("dmxValues", this.dmxValues, dmxValues); + this.dmxValues = dmxValues; + } + + @Override + public void activate() { + if(!this.isActive) { + this.isActive = true; + propertySupport.firePropertyChange("isActive", false, true); + } + + + } + + @Override + public void deactivate() { + this.isActive = false; + propertySupport.firePropertyChange("isActive", true, false); + } + + public LightingSceneType getLightingSceneType() { + return LightingSceneType.LIGHTING_MOOD; + } +} diff --git a/src/lightControlSoftware/src/model/lightingScene/lightingMood/LightingMoodRepository.java b/src/lightControlSoftware/src/model/lightingScene/lightingMood/LightingMoodRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..9231ee77e1d428e8c9515f4b0de2e43c07aa742a --- /dev/null +++ b/src/lightControlSoftware/src/model/lightingScene/lightingMood/LightingMoodRepository.java @@ -0,0 +1,38 @@ +package model.lightingScene.lightingMood; + + +import java.util.Map; + +import model.generic.PropertyItem; + +import java.util.HashMap; + +public class LightingMoodRepository extends PropertyItem { + private Map<String, LightingMood> lightingMoods; + + public LightingMoodRepository() { + this.lightingMoods = new HashMap<>(); + } + + public void addLightingMood(LightingMood lightingMood) { + if(this.lightingMoods.containsKey(lightingMood.getName())) { + throw new IllegalArgumentException("Es existiert bereits eine Lichtstimmung mit diesem Namen"); + } + + this.lightingMoods.put(lightingMood.getName(), lightingMood); + this.propertySupport.firePropertyChange("lightingMoods", null, lightingMood); + } + + public LightingMood getLightingMood(String name) { + return lightingMoods.get(name); + } + + public void removeLightingMood(String name) { + this.propertySupport.firePropertyChange("lightingMoods", this.lightingMoods.get(name), null); + this.lightingMoods.remove(name); + } + + public Map<String, LightingMood> getLightingMoodMap() { + return this.lightingMoods; + } +} \ No newline at end of file diff --git a/src/lightControlSoftware/src/model/preset/Preset.java b/src/lightControlSoftware/src/model/preset/Preset.java new file mode 100644 index 0000000000000000000000000000000000000000..5192734d9e55f219cfead516347b90b0b5b7e9a1 --- /dev/null +++ b/src/lightControlSoftware/src/model/preset/Preset.java @@ -0,0 +1,112 @@ +package model.preset; + +import model.KiwiModelHandler; +import model.fixture.DmxValues; +import model.fixture.Fixture; +import model.generic.PropertyItem; +import model.group.Group; +import model.lightController.LightControllable; +import model.lightingScene.LightingScene; +import model.lightingScene.LightingScene.LightingSceneType; +import model.lightingScene.composition.Composition; +import model.lightingScene.lightingMood.LightingMood; + +public class Preset extends PropertyItem{ + private static int numberOfPresets = 0; + private int id; + private Group group; + private LightingScene lightingScene; + private State state = State.DEAKTIV; + private LightControllable lightController = KiwiModelHandler.getLightController(); + + public static enum State { + AKTIV, + PARTAKTIV, + DEAKTIV + } + + public Preset() { + this.id = Preset.numberOfPresets; + Preset.numberOfPresets++; + } + + public Preset(Group group, LightingScene lightingScene) { + super(); + this.id = Preset.numberOfPresets; + this.group = group; + this.lightingScene = lightingScene; + Preset.numberOfPresets++; + } + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + public LightingScene getLightingScene() { + return lightingScene; + } + + public void setLightingScene(LightingScene lightingScene) { + this.lightingScene = lightingScene; + } + + public int getId() { + return id; + } + + public State getState() { + return state; + } + + private void setState(State state) { + this.propertySupport.firePropertyChange("state", this.state, state); + this.state = state; + } + + public void activate() { + this.setState(State.AKTIV); + this.group.setCurrentState(Group.State.AKTIV); + this.lightingScene.activate(); + } + + public void deactivate() { + this.setState(State.DEAKTIV); + this.group.setCurrentState(Group.State.DEAKTIV); + this.lightingScene.deactivate(); + } + + public void updatePreset() { + if(lightingScene != null) { + this.lightController.clearPreset(this.id); + if(lightingScene.getLightingSceneType() == LightingSceneType.LIGHTING_MOOD) { + group.getFixtureRepository().getFixtureMap().forEach((String name, Fixture fixture) -> { + this.setDmxValueForPreset(fixture.getAddress(), ((LightingMood)lightingScene).getDmxValues()); + }); + } else if (lightingScene.getLightingSceneType() == LightingSceneType.COMPOSITION) { + group.getFixtureRepository().getFixtureMap().forEach((String name, Fixture fixture) -> { + this.setDmxValueForPreset(fixture.getAddress(), ((Composition)lightingScene).getDmxValuesForFixture(name)); + }); + } + } + } + + private void setDmxValueForPreset(int address, DmxValues dmxValues) { + System.out.println(String.format("Preset %d, hat einen Blauwert von: %d.", this.group.getId(), Byte.toUnsignedInt(dmxValues.getIntensityBlue()))); + lightController.setPreset(this.id, this.group.getId(), address, dmxValues.getIntensityRed()); + lightController.setPreset(this.id, this.group.getId(), address+1, dmxValues.getIntensityGreen()); + lightController.setPreset(this.id, this.group.getId(), address+2, dmxValues.getIntensityBlue()); + lightController.setPreset(this.id, this.group.getId(), address+3, dmxValues.getIntensityMain()); + lightController.setPreset(this.id, this.group.getId(), address+4, dmxValues.getStropeRate()); + } + + @Override + protected void finalize() { + Preset.numberOfPresets--; + } + + +} diff --git a/src/lightControlSoftware/src/model/preset/PresetRepository.java b/src/lightControlSoftware/src/model/preset/PresetRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..209d9d682a1dec5441e5927e7a91efce99dd91ff --- /dev/null +++ b/src/lightControlSoftware/src/model/preset/PresetRepository.java @@ -0,0 +1,40 @@ +package model.preset; + +import java.util.Map; + +import model.generic.PropertyItem; + +import java.util.HashMap; + +public class PresetRepository extends PropertyItem{ + Map<Integer, Preset> presets; + + public PresetRepository() { + this.presets = new HashMap<>(); + } + + public void loadPrests() { + for(int i = 0; i < 6; i++) { + this.addPreset(new Preset()); + } + } + + public void addPreset(Preset preset) { + this.presets.put(preset.getId(), preset); + this.propertySupport.firePropertyChange("presets", null, preset); + } + + public void removePreset(Preset preset) { + preset.deactivate(); + this.propertySupport.firePropertyChange("presets", preset, null); + this.presets.remove(preset.getId()); + } + + public Preset getPreset(int presetId) { + return this.presets.get(presetId); + } + + public Map<Integer, Preset> getPresetsMap() { + return this.presets; + } +} diff --git a/src/lightControlSoftware/src/view/KiwiViewHandler.java b/src/lightControlSoftware/src/view/KiwiViewHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..ad9987d39cf15bc224d14f915fa024a85a240485 --- /dev/null +++ b/src/lightControlSoftware/src/view/KiwiViewHandler.java @@ -0,0 +1,41 @@ +package view; + +import javafx.application.Platform; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.image.Image; +import javafx.stage.Stage; +import view.mainScene.MainSceneController; +import viewModel.KiwiViewModelHandler; + +public class KiwiViewHandler{ + + private Stage stage; + private KiwiViewModelHandler viewModelHandler; + + public KiwiViewHandler(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.viewModelHandler = viewModelHandler; + } + + public void start() throws Exception { + FXMLLoader loader = new FXMLLoader(getClass().getResource("mainScene/MainScene.fxml")); + Parent root; + root = loader.load(); + MainSceneController mainSceneController= loader.getController(); + mainSceneController.init(viewModelHandler); + Scene scene = new Scene(root); + scene.getStylesheets().add("style/Style.css"); + this.stage.setMinWidth(800); + this.stage.setMinHeight(625); + this.stage.setTitle("KIWI Illumination Weeny Interface"); + this.stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + this.stage.setScene(scene); + this.stage.show(); + + this.stage.setOnCloseRequest(event -> { + Platform.exit(); + }); + } +} diff --git a/src/lightControlSoftware/src/view/composition/CompositionListItem.java b/src/lightControlSoftware/src/view/composition/CompositionListItem.java new file mode 100644 index 0000000000000000000000000000000000000000..63506bc4fd361171207c29b2192e957722659620 --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/CompositionListItem.java @@ -0,0 +1,225 @@ +package view.composition; + +import java.io.IOException; +import java.util.Optional; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import view.composition.editDeletePanel.EditDeleteCompositionController; +import view.elements.ThreeStageSwitchButton; +import viewModel.KiwiViewModelHandler; +import viewModel.composition.CompositionVM; +import viewModel.group.GroupVM; +import viewModel.group.GroupVM.State; + +public class CompositionListItem extends AnchorPane{ + + private CompositionVM compositionVM; + private String compositionName; + private BooleanProperty selected; + private GroupVM groupVM; + + public CompositionListItem(CompositionVM compositionVM, GroupVM groupVM, KiwiViewModelHandler viewModelHandler) { + this.compositionVM = compositionVM; + this.groupVM = groupVM; + this.compositionName = compositionVM.getCompositionName(); + selected = new SimpleBooleanProperty(false); + + setMaxHeight(80.0); + setMinHeight(80.0); + setPrefHeight(80.0); + setMaxWidth(200.0); + setMinWidth(200.0); + setPrefWidth(200.0); + FlowPane.setMargin(this, new Insets(5.0, 5.0, 5.0, 5.0)); + + VBox vBox = new VBox(); + vBox.setAlignment(Pos.CENTER_LEFT); + vBox.setLayoutX(7.0); + vBox.setLayoutY(2.0); + vBox.setMaxWidth(100.0); + AnchorPane.setBottomAnchor(vBox, 1.0); + AnchorPane.setLeftAnchor(vBox, 5.0); + AnchorPane.setRightAnchor(vBox, 5.0); + AnchorPane.setTopAnchor(vBox, 1.0); + + Label lableCompositionName = new Label(compositionName); + lableCompositionName.setAlignment(Pos.TOP_LEFT); + lableCompositionName.setMaxHeight(34.0); + lableCompositionName.setWrapText(true); + lableCompositionName.textProperty().bind(this.compositionVM.compositionNameProperty()); + VBox.setVgrow(lableCompositionName, Priority.ALWAYS); + VBox.setMargin(lableCompositionName, new Insets(5.0, 0.0, 0.0, 0.0)); + + AnchorPane buttonArea = new AnchorPane(); + + VBox vBoxSwitchButton = new VBox(); + vBoxSwitchButton.setAlignment(Pos.CENTER_LEFT); + vBoxSwitchButton.setLayoutX(-1.0); + vBoxSwitchButton.setLayoutY(-1.0); + AnchorPane.setBottomAnchor(vBoxSwitchButton, 0.0); + AnchorPane.setLeftAnchor(vBoxSwitchButton, 5.0); + AnchorPane.setTopAnchor(vBoxSwitchButton, 0.0); + + ThreeStageSwitchButton switchButton = new ThreeStageSwitchButton(); + switchButton.setMaxHeight(20.0); + switchButton.setMinHeight(20.0); + switchButton.setPrefHeight(20.0); + switchButton.setMaxWidth(45.0); + switchButton.setMinWidth(45.0); + switchButton.setPrefWidth(45.0); + + if(this.compositionVM.compositionIsActiveProperty().get()) { + switchButton.buttonStateProperty().set(State.ON); + } + + this.compositionVM.compositionIsActiveProperty().addListener((object, oldValue, newValue) -> { + if(newValue) { + if(switchButton.buttonStateProperty().get() != State.ON) { + //switchButton.buttonStateProperty().set(State.ON); + } + } else { + if(switchButton.buttonStateProperty().get() != State.OFF) { + switchButton.buttonStateProperty().set(State.OFF); + } + } + }); + + + switchButton.buttonStateProperty().addListener((object, oldValue, newValue) -> { + switch(newValue) { + case ON: + this.groupVM.activateComposition(this.compositionVM); + break; + case OFF: + this.groupVM.deactivateComposition(this.compositionVM); + break; + default: + break; + } + }); + + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_RIGHT); + AnchorPane.setBottomAnchor(hBox, 0.0); + AnchorPane.setRightAnchor(hBox, 5.0); + AnchorPane.setTopAnchor(hBox, 0.0); + + Image icon1 = new Image("images/Edit.png"); + ImageView imageView1 = new ImageView(); + imageView1.setImage(icon1); + imageView1.setFitHeight(25.0); + imageView1.setFitWidth(25.0); + imageView1.setPickOnBounds(true); + imageView1.setPreserveRatio(true); + + + Button buttonEditComposition = new Button(); + buttonEditComposition.setMnemonicParsing(false); + buttonEditComposition.setStyle("-fx-background-color: none"); + buttonEditComposition.setOnAction(event -> { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../composition/editDeletePanel/EditDeleteComposition.fxml")); + Parent editDeleteCompositionPanel = loader.load(); + EditDeleteCompositionController editDeleteCompositionController = loader.getController(); + Scene scene = new Scene(editDeleteCompositionPanel); + Stage compositionDialog = new Stage(); + editDeleteCompositionController.init(compositionDialog, viewModelHandler); + editDeleteCompositionController.setGroup(this.groupVM.getGroupName()); + editDeleteCompositionController.setComposition(compositionName); + compositionDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + compositionDialog.setScene(scene); + compositionDialog.setTitle("Komposition bearbeiten/l�schen"); + compositionDialog.showAndWait(); + editDeleteCompositionController = null; + loader = null; + } catch (IOException e) { + e.printStackTrace(); + } + }); + buttonEditComposition.setGraphic(imageView1); + + Image icon2 = new Image("images/Delete.png"); + ImageView imageView2 = new ImageView(); + imageView2.setImage(icon2); + imageView2.setFitHeight(25.0); + imageView2.setFitWidth(25.0); + imageView2.setPickOnBounds(true); + imageView2.setPreserveRatio(true); + + + Button buttonDeleteComposition = new Button(); + buttonDeleteComposition.setMnemonicParsing(false); + buttonDeleteComposition.setStyle("-fx-background-color: none"); + buttonDeleteComposition.setOnAction(event -> { + Alert alert = new Alert(AlertType.CONFIRMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Komposition l�schen"); + alert.setHeaderText(String.format("Sind Sie sicher, dass Sie die Komposition %s l�schen m�chten", this.getLightingMoodName())); + ButtonType buttonDelete = new ButtonType("Komposition l�schen"); + ButtonType buttonCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + alert.getButtonTypes().setAll(buttonDelete, buttonCancel); + Optional<ButtonType> result = alert.showAndWait(); + if (result.orElseThrow() == buttonDelete) { + this.groupVM.removeComposition(this.compositionVM); + } + }); + buttonDeleteComposition.setGraphic(imageView2); + + + vBoxSwitchButton.getChildren().add(switchButton); + hBox.getChildren().addAll(buttonEditComposition, buttonDeleteComposition); + buttonArea.getChildren().addAll(vBoxSwitchButton, hBox); + vBox.getChildren().addAll(lableCompositionName, buttonArea); + getChildren().addAll(vBox); + getStyleClass().addAll("list-item", "item-diselected"); + + this.selected.bind(this.compositionVM.selectedProperty()); + + this.selected.addListener((object, oldValue, newValue) -> { + if(newValue) { + this.getStyleClass().add("item-selected"); + this.getStyleClass().remove("item-diselected"); + } else { + this.getStyleClass().add("item-diselected"); + this.getStyleClass().remove("item-selected"); + } + }); + + this.setOnMouseClicked(event -> { + this.compositionVM.setCompositionIsSeleceted(true); + }); + } + + public boolean isSelected() { + return selected.get(); + } + + public BooleanProperty selectedProperty() { + return this.selected; + } + + public String getLightingMoodName() { + return this.compositionName; + } +} diff --git a/src/lightControlSoftware/src/view/composition/createPanel/CreateComposition.fxml b/src/lightControlSoftware/src/view/composition/createPanel/CreateComposition.fxml new file mode 100644 index 0000000000000000000000000000000000000000..11b675721bcd50a47f48d61fde9fa0b520d3c259 --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/createPanel/CreateComposition.fxml @@ -0,0 +1,244 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ColorPicker?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.Slider?> +<?import javafx.scene.control.Spinner?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.paint.Color?> +<?import javafx.scene.text.Font?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="350.0" minWidth="550.0" prefHeight="500.0" prefWidth="800.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.composition.createPanel.CreateCompositionController"> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"> + <children> + <BorderPane HBox.hgrow="ALWAYS"> + <center> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT" VBox.vgrow="NEVER"> + <children> + <Label minWidth="50.0" text="Farbe" /> + <ColorPicker fx:id="colorPicker"> + <HBox.margin> + <Insets /> + </HBox.margin> + <value> + <Color /> + </value> + </ColorPicker> + </children> + <opaqueInsets> + <Insets /> + </opaqueInsets> + </HBox> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderMainIntensity" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Dimmer" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets /> + </BorderPane.margin> + </Label> + </left> + <right> + <Spinner fx:id="spinnerMainIntensity" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderStrope" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Strobe" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets /> + </BorderPane.margin> + </Label> + </left> + <right> + <Spinner fx:id="spinnerStrope" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderRed" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Rot" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerRed" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderGreen" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Grün" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerGreen" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderBlue" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Blau" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerBlue" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + </children> + <BorderPane.margin> + <Insets top="10.0" /> + </BorderPane.margin> + </VBox> + </center> + <HBox.margin> + <Insets left="20.0" /> + </HBox.margin> + </BorderPane> + </children> + </HBox> + </children> + </AnchorPane> + </center> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#saveComposition" text="Komposition erstellen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> + <left> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT"> + <children> + <Label minWidth="75.0" prefWidth="75.0" text="Gruppe" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </Label> + <ComboBox fx:id="comboBoxGroup" minWidth="150.0" onAction="#selectGroup" /> + </children> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + </HBox> + <HBox alignment="CENTER_LEFT"> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + <children> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin></Label> + <TextField fx:id="textfieldName" /> + </children> + <HBox.margin> + <Insets right="10.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + <HBox alignment="CENTER_LEFT"> + <children> + <Label minWidth="75.0" prefWidth="75.0" text="Lampe" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </Label> + <ComboBox fx:id="comboBoxFixture" minWidth="150.0" onAction="#selectFixture" /> + </children> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + </HBox> + <AnchorPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS"> + <children> + <AnchorPane prefHeight="200.0" prefWidth="200.0" styleClass="section" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="10.0"> + <children> + <ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <content> + <ListView fx:id="lightMoodList" prefHeight="200.0" prefWidth="200.0"> + <styleClass> + <String fx:value="list-cell" /> + <String fx:value="white-background" /> + </styleClass> + </ListView> + </content> + </ScrollPane> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </padding> + </AnchorPane> + <Label styleClass="section-headline" text="Lichtstimmung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> + <VBox.margin> + <Insets right="5.0" top="10.0" /> + </VBox.margin> + </AnchorPane> + </children> + <BorderPane.margin> + <Insets left="10.0" /> + </BorderPane.margin> + </VBox> + </left> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/composition/createPanel/CreateCompositionController.java b/src/lightControlSoftware/src/view/composition/createPanel/CreateCompositionController.java new file mode 100644 index 0000000000000000000000000000000000000000..16c50b73dfd178836464675fbd952c76a27fd1c4 --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/createPanel/CreateCompositionController.java @@ -0,0 +1,333 @@ +package view.composition.createPanel; + +import javafx.fxml.FXML; + +import javafx.scene.control.ColorPicker; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.control.ToggleGroup; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.image.Image; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.scene.control.Slider; +import javafx.scene.control.ListView; +import javafx.scene.control.RadioButton; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Spinner; +import javafx.scene.control.SpinnerValueFactory; +import javafx.scene.layout.BorderPane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import model.lightingScene.composition.Composition; +import viewModel.KiwiViewModelHandler; +import viewModel.composition.CompositionVM; +import viewModel.fixture.DmxValuesVM; +import viewModel.fixture.FixtureVM; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; +import viewModel.lightingMood.LightingMoodVM; + +public class CreateCompositionController { + @FXML + private BorderPane root; + @FXML + private ColorPicker colorPicker; + @FXML + private Slider sliderMainIntensity; + @FXML + private Spinner<Integer> spinnerMainIntensity; + @FXML + private Slider sliderStrope; + @FXML + private Spinner<Integer> spinnerStrope; + @FXML + private Slider sliderRed; + @FXML + private Spinner<Integer> spinnerRed; + @FXML + private Slider sliderGreen; + @FXML + private Spinner<Integer> spinnerGreen; + @FXML + private Slider sliderBlue; + @FXML + private Spinner<Integer> spinnerBlue; + @FXML + private Button buttonSave; + @FXML + private Button buttonCancel; + @FXML + private ComboBox<String> comboBoxGroup; + @FXML + private TextField textfieldName; + @FXML + private ComboBox<String> comboBoxFixture; + @FXML + private ListView<RadioButton> lightMoodList; + + private Stage stage; + private GroupVM groupVM; + private FixtureVM fixtureVM; + private GroupRepositoryVM groupRepositoryVM; + private ToggleGroup toggelGroup = new ToggleGroup(); + private ObservableList<String> groupNames = FXCollections.observableArrayList(); + private ObservableList<String> fixtureNames = FXCollections.observableArrayList(); + private ObservableList<RadioButton> lightingMoods = FXCollections.observableArrayList(); + + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); + this.spinnerMainIntensity.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerStrope.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerRed.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerGreen.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerBlue.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.lightMoodList.setItems(lightingMoods); + this.addListener(); + this.loadGroups(); + this.updateLightingMoodList(); + this.loadFixtures(); + } + + // Event Listener on Button[#buttonSave].onAction + @FXML + public void saveComposition(ActionEvent event) { + if(this.isDataValid()) { + + try { + CompositionVM compositionVM = new CompositionVM(new Composition(this.textfieldName.getText())); + this.fixtureNames.forEach(fixtureName -> { + FixtureVM fixtureVM = this.groupVM.getFixtureRepositoryVM().getFixtureVM(fixtureName); + compositionVM.setDmxValuesForFixture(fixtureVM.getFixtureName(), fixtureVM.getDmxValuesVM()); + }); + + this.groupRepositoryVM + .getGroupVM(this.comboBoxGroup.getValue()) + .addComposition(compositionVM); + this.stage.close(); + } catch (IllegalArgumentException e) { + Alert alert = new Alert(AlertType.ERROR); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler beim Erstellen einer Lichtstimmung."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + // Event Listener on ComboBox[#comboBoxGroup].onAction + @FXML + public void selectGroup(ActionEvent event) { + if(!(this.comboBoxGroup.getValue() == null)) { + this.groupVM = groupRepositoryVM.getGroupVM(this.comboBoxGroup.getValue()); + this.updateLightingMoodList(); + this.loadFixtures(); + } + } + // Event Listener on ComboBox[#comboBoxFixture].onAction + @FXML + public void selectFixture(ActionEvent event) { + if(!(this.comboBoxFixture.getValue() == null)) { + this.fixtureVM = this.groupVM.getFixtureRepositoryVM().getFixtureVM(this.comboBoxFixture.getValue()); + this.lightMoodList.getItems().forEach(radioButton -> { + if(radioButton.getText().equals(fixtureVM.getLightingMoodName())) { + this.updateSliderDmxValues(this.fixtureVM.getDmxValuesVM()); + radioButton.selectedProperty().set(true); + } + }); + } + } + + private void addListener() { + + this.addSpinnerListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSpinnerListener(this.spinnerStrope, this.sliderStrope); + this.addSpinnerListener(this.spinnerRed, this.sliderRed); + this.addSpinnerListener(this.spinnerGreen, this.sliderGreen); + this.addSpinnerListener(this.spinnerBlue, this.sliderBlue); + + this.addSliderListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSliderListener(this.spinnerStrope, this.sliderStrope); + this.addSliderListener(this.spinnerRed, this.sliderRed); + this.addSliderListener(this.spinnerGreen, this.sliderGreen); + this.addSliderListener(this.spinnerBlue, this.sliderBlue); + + this.colorPicker.valueProperty().addListener((onject, oldValue, newValue) -> { + this.sliderRed.setValue(newValue.getRed()*255); + this.sliderGreen.setValue(newValue.getGreen()*255); + this.sliderBlue.setValue(newValue.getBlue()*255); + }); + + this.sliderRed.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + (double)newValue/255, + this.sliderGreen.getValue()/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderGreen.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + (double)newValue/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderBlue.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + this.sliderGreen.getValue()/255, + (double)newValue/255, 1 + )); + }); + } + + private void addSpinnerListener (Spinner<Integer> spinner, Slider slider) { + spinner.getValueFactory().valueProperty().addListener((object, oldValue, newValue) -> { + slider.valueProperty().set(newValue.doubleValue()); + }); + } + + private void addSliderListener (Spinner<Integer> spinner, Slider slider) { + slider.valueProperty().addListener((object, oldValue, newValue) -> { + if(this.toggelGroup.getSelectedToggle() != null + && this.fixtureVM.getLightingMoodName().equals(((RadioButton)toggelGroup.getSelectedToggle()).getText())) { + this.updateFixtureDmxValues(); + if(!this.toggelGroup.getToggles().get(0).selectedProperty().get()) { + this.toggelGroup.getToggles().get(0).selectedProperty().set(true); + } + } + spinner.getValueFactory().setValue(newValue.intValue()); + }); + } + + private void loadGroups() { + this.groupNames.clear(); + this.groupRepositoryVM.groupsListProperty().forEach(groupVM -> { + this.groupNames.add(groupVM.getGroupName()); + }); + this.groupVM = this.groupRepositoryVM.getGroupVM(this.groupNames.get(0)); + this.comboBoxGroup.setItems(this.groupNames); + this.comboBoxGroup.setValue(this.groupNames.get(0)); + } + + private void loadFixtures() { + this.fixtureNames.clear(); + this.groupVM.getFixtureRepositoryVM().fixtureListProperty().forEach(fixtureVM -> { + this.fixtureNames.add(fixtureVM.getFixtureName()); + }); + this.fixtureVM = this.groupVM.getFixtureRepositoryVM().getFixtureVM(this.fixtureNames.get(0)); + this.comboBoxFixture.setItems(this.fixtureNames); + this.comboBoxFixture.setValue(this.fixtureNames.get(0)); + this.lightMoodList.getItems().forEach(radioButton -> { + if(radioButton.getText().equals(this.fixtureVM.getLightingMoodName())) { + this.updateSliderDmxValues(this.fixtureVM.getDmxValuesVM()); + radioButton.selectedProperty().set(true); + } + }); + + } + + private void updateLightingMoodList() { + this.lightingMoods.clear(); + this.toggelGroup = new ToggleGroup(); + this.toggelGroup.selectedToggleProperty().addListener((object, oldValue, newValue) -> { + if(this.fixtureVM != null) { + RadioButton radioButton = (RadioButton) newValue; + if(!radioButton.getText().equals("Benutzerdefeniert")) { + LightingMoodVM lightingMoodVM = this.groupVM.getLightingMoodRepositoryVM().getLightingMood(radioButton.getText()); + this.updateSliderDmxValues(lightingMoodVM.getDmxValuesVM()); + this.updateFixtureDmxValues(lightingMoodVM.getDmxValuesVM()); + this.fixtureVM.setLightingMoodName(radioButton.getText()); + } else { + this.fixtureVM.setLightingMoodName(radioButton.getText()); + } + } + }); + + RadioButton userSpezified = new RadioButton("Benutzerdefeniert"); + userSpezified.setToggleGroup(toggelGroup); + this.lightingMoods.add(userSpezified); + this.groupVM.getLightingMoodRepositoryVM().lightingMoodListProperty().forEach(lightingMood -> { + RadioButton lightingMoodRadioButton = new RadioButton(lightingMood.getLightingMoodName()); + lightingMoodRadioButton.setToggleGroup(toggelGroup); + this.lightingMoods.add(lightingMoodRadioButton); + }); + } + + private void updateSliderDmxValues(DmxValuesVM dmxValuesVM) { + this.sliderMainIntensity.valueProperty().set(dmxValuesVM.getMainIntensity()); + this.sliderStrope.valueProperty().set(dmxValuesVM.getStrope()); + this.sliderRed.valueProperty().set(dmxValuesVM.getRed()); + this.sliderGreen.valueProperty().set(dmxValuesVM.getGreen()); + this.sliderBlue.valueProperty().set(dmxValuesVM.getBlue()); + } + + private void updateFixtureDmxValues() { + this.fixtureVM.getDmxValuesVM().setMainIntensity(this.sliderMainIntensity.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setStrope(this.sliderStrope.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setRed(this.sliderRed.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setGreen(this.sliderGreen.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setBlue(this.sliderBlue.valueProperty().getValue().intValue()); + } + + private void updateFixtureDmxValues(DmxValuesVM dmxValuesVM) { + this.fixtureVM.getDmxValuesVM().setMainIntensity(dmxValuesVM.getMainIntensity()); + this.fixtureVM.getDmxValuesVM().setStrope(dmxValuesVM.getStrope()); + this.fixtureVM.getDmxValuesVM().setRed(dmxValuesVM.getRed()); + this.fixtureVM.getDmxValuesVM().setGreen(dmxValuesVM.getGreen()); + this.fixtureVM.getDmxValuesVM().setBlue(dmxValuesVM.getBlue()); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textfieldName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + public void setGroup(String name) { + this.comboBoxGroup.valueProperty().set(name); + this.groupVM = groupRepositoryVM.getGroupVM(name); + this.updateLightingMoodList(); + this.loadFixtures(); + } +} diff --git a/src/lightControlSoftware/src/view/composition/editDeletePanel/EditDeleteComposition.fxml b/src/lightControlSoftware/src/view/composition/editDeletePanel/EditDeleteComposition.fxml new file mode 100644 index 0000000000000000000000000000000000000000..195f1edeb445acdee85d14bdc7acbf51bacc258e --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/editDeletePanel/EditDeleteComposition.fxml @@ -0,0 +1,257 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ColorPicker?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.Slider?> +<?import javafx.scene.control.Spinner?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.paint.Color?> +<?import javafx.scene.text.Font?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="350.0" minWidth="550.0" prefHeight="500.0" prefWidth="800.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.composition.editDeletePanel.EditDeleteCompositionController"> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"> + <children> + <BorderPane HBox.hgrow="ALWAYS"> + <center> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT" VBox.vgrow="NEVER"> + <children> + <Label minWidth="50.0" text="Farbe" /> + <ColorPicker fx:id="colorPicker"> + <HBox.margin> + <Insets /> + </HBox.margin> + <value> + <Color /> + </value> + </ColorPicker> + </children> + <opaqueInsets> + <Insets /> + </opaqueInsets> + </HBox> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderMainIntensity" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Dimmer" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets /> + </BorderPane.margin> + </Label> + </left> + <right> + <Spinner fx:id="spinnerMainIntensity" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderStrope" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Strobe" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets /> + </BorderPane.margin> + </Label> + </left> + <right> + <Spinner fx:id="spinnerStrope" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderRed" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Rot" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerRed" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderGreen" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Grün" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerGreen" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderBlue" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="50.0" text="Blau" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerBlue" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + </children> + <BorderPane.margin> + <Insets top="10.0" /> + </BorderPane.margin> + </VBox> + </center> + <HBox.margin> + <Insets left="20.0" /> + </HBox.margin> + </BorderPane> + </children> + </HBox> + </children> + </AnchorPane> + </center> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#saveComposition" text="Speichern"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> + <left> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT"> + <children> + <Label minWidth="75.0" prefWidth="75.0" text="Gruppe" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </Label> + <ComboBox fx:id="comboBoxGroup" minWidth="150.0" onAction="#selectGroup" /> + </children> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + </HBox> + <HBox alignment="CENTER_LEFT"> + <children> + <Label minWidth="75.0" prefWidth="75.0" text="Komposition" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </Label> + <ComboBox fx:id="comboBoxComposition" minWidth="150.0" onAction="#selectComposition" /> + </children> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + </HBox> + <HBox alignment="CENTER_LEFT"> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + <children> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin></Label> + <TextField fx:id="textfieldName" /> + </children> + <HBox.margin> + <Insets right="10.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + <HBox alignment="CENTER_LEFT"> + <children> + <Label minWidth="75.0" prefWidth="75.0" text="Lampe" HBox.hgrow="NEVER"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </Label> + <ComboBox fx:id="comboBoxFixture" minWidth="150.0" onAction="#selectFixture" /> + </children> + <VBox.margin> + <Insets top="10.0" /> + </VBox.margin> + </HBox> + <AnchorPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS"> + <children> + <AnchorPane prefHeight="200.0" prefWidth="200.0" styleClass="section" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="10.0"> + <children> + <ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <content> + <ListView fx:id="lightMoodList" prefHeight="200.0" prefWidth="200.0"> + <styleClass> + <String fx:value="list-cell" /> + <String fx:value="white-background" /> + </styleClass> + </ListView> + </content> + </ScrollPane> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </padding> + </AnchorPane> + <Label styleClass="section-headline" text="Lichtstimmung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> + <VBox.margin> + <Insets right="5.0" top="10.0" /> + </VBox.margin> + </AnchorPane> + </children> + <BorderPane.margin> + <Insets left="10.0" /> + </BorderPane.margin> + </VBox> + </left> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/composition/editDeletePanel/EditDeleteCompositionController.java b/src/lightControlSoftware/src/view/composition/editDeletePanel/EditDeleteCompositionController.java new file mode 100644 index 0000000000000000000000000000000000000000..cb438f126b00682764d6688ae4db8f74d1b176d2 --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/editDeletePanel/EditDeleteCompositionController.java @@ -0,0 +1,394 @@ +package view.composition.editDeletePanel; + +import javafx.fxml.FXML; + +import javafx.scene.control.ColorPicker; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; + +import javafx.scene.control.TextField; +import javafx.scene.control.ToggleGroup; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.image.Image; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; + +import javafx.scene.control.Slider; + +import javafx.scene.control.ListView; +import javafx.scene.control.RadioButton; +import javafx.scene.control.ComboBox; + +import javafx.scene.control.Spinner; +import javafx.scene.control.SpinnerValueFactory; +import javafx.scene.layout.BorderPane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import viewModel.KiwiViewModelHandler; +import viewModel.composition.CompositionRepositoryVM; +import viewModel.composition.CompositionVM; +import viewModel.fixture.DmxValuesVM; +import viewModel.fixture.FixtureVM; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; +import viewModel.lightingMood.LightingMoodVM; + +public class EditDeleteCompositionController { + @FXML + private BorderPane root; + @FXML + private ColorPicker colorPicker; + @FXML + private Slider sliderMainIntensity; + @FXML + private Spinner<Integer> spinnerMainIntensity; + @FXML + private Slider sliderStrope; + @FXML + private Spinner<Integer> spinnerStrope; + @FXML + private Slider sliderRed; + @FXML + private Spinner<Integer> spinnerRed; + @FXML + private Slider sliderGreen; + @FXML + private Spinner<Integer> spinnerGreen; + @FXML + private Slider sliderBlue; + @FXML + private Spinner<Integer> spinnerBlue; + @FXML + private Button buttonSave; + @FXML + private Button buttonCancel; + @FXML + private ComboBox<String> comboBoxGroup; + @FXML + private ComboBox<String> comboBoxComposition; + @FXML + private TextField textfieldName; + @FXML + private ComboBox<String> comboBoxFixture; + @FXML + private ListView<RadioButton> lightMoodList; + + private Stage stage; + private GroupVM groupVM; + private FixtureVM fixtureVM; + private CompositionVM compositionVM; + private GroupRepositoryVM groupRepositoryVM; + private KiwiViewModelHandler viewModelHandler; + private ToggleGroup toggelGroup = new ToggleGroup(); + private CompositionRepositoryVM compositionRepositoryVM; + private ObservableList<String> groupNames = FXCollections.observableArrayList(); + private ObservableList<String> fixtureNames = FXCollections.observableArrayList(); + private ObservableList<String> compositionNames = FXCollections.observableArrayList(); + private ObservableList<RadioButton> lightingMoods = FXCollections.observableArrayList(); + + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.viewModelHandler = viewModelHandler; + this.groupRepositoryVM = this.viewModelHandler.getGroupRepositoryVM(); + this.spinnerMainIntensity.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerStrope.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerRed.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerGreen.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerBlue.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.lightMoodList.setItems(lightingMoods); + this.addListener(); + this.loadGroups(); + this.loadCompositions(); + this.updateLightingMoodList(); + this.loadFixtures(); + this.updateFixtures(); + + } + + + // Event Listener on Button[#buttonSave].onAction + @FXML + public void saveComposition(ActionEvent event) { + if(this.isDataValid()) { + try { + this.compositionVM.setCompositionName(this.textfieldName.getText()); + this.fixtureNames.forEach(fixtureName -> { + FixtureVM fixtureVM = this.groupVM.getFixtureRepositoryVM().getFixtureVM(fixtureName); + this.compositionVM.setDmxValuesForFixture(fixtureVM.getFixtureName(), fixtureVM.getDmxValuesVM()); + }); + this.stage.close(); + } catch (IllegalArgumentException e) { + Alert alert = new Alert(AlertType.ERROR); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler beim Erstellen einer Lichtstimmung."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + // Event Listener on ComboBox[#comboBoxGroup].onAction + @FXML + public void selectGroup(ActionEvent event) { + if(!(this.comboBoxGroup.getValue() == null)) { + this.groupVM = groupRepositoryVM.getGroupVM(this.comboBoxGroup.getValue()); + this.loadCompositions(); + this.updateLightingMoodList(); + this.updateFixtures(); + this.loadFixtures(); + } + } + // Event Listener on ComboBox[#comboBoxComposition].onAction + @FXML + public void selectComposition(ActionEvent event) { + this.compositionVM = this.groupVM.getCompositionRepositoryVM().getComposition(this.comboBoxComposition.getValue()); + this.textfieldName.textProperty().set(this.compositionVM.getCompositionName()); + this.updateFixtures(); + this.updateSliderDmxValues(this.fixtureVM.getDmxValuesVM()); + } + // Event Listener on ComboBox[#comboBoxFixture].onAction + @FXML + public void selectFixture(ActionEvent event) { + if(!(this.comboBoxFixture.getValue() == null)) { + this.fixtureVM = this.groupVM.getFixtureRepositoryVM().getFixtureVM(this.comboBoxFixture.getValue()); + this.lightMoodList.getItems().forEach(radioButton -> { + if(radioButton.getText().equals(fixtureVM.getLightingMoodName())) { + this.updateSliderDmxValues(this.fixtureVM.getDmxValuesVM()); + radioButton.selectedProperty().set(true); + } + }); + } + } + + private void addListener() { + + this.addSpinnerListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSpinnerListener(this.spinnerStrope, this.sliderStrope); + this.addSpinnerListener(this.spinnerRed, this.sliderRed); + this.addSpinnerListener(this.spinnerGreen, this.sliderGreen); + this.addSpinnerListener(this.spinnerBlue, this.sliderBlue); + + this.addSliderListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSliderListener(this.spinnerStrope, this.sliderStrope); + this.addSliderListener(this.spinnerRed, this.sliderRed); + this.addSliderListener(this.spinnerGreen, this.sliderGreen); + this.addSliderListener(this.spinnerBlue, this.sliderBlue); + + this.colorPicker.valueProperty().addListener((onject, oldValue, newValue) -> { + this.sliderRed.setValue(newValue.getRed()*255); + this.sliderGreen.setValue(newValue.getGreen()*255); + this.sliderBlue.setValue(newValue.getBlue()*255); + }); + + this.sliderRed.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + (double)newValue/255, + this.sliderGreen.getValue()/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderGreen.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + (double)newValue/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderBlue.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + this.sliderGreen.getValue()/255, + (double)newValue/255, 1 + )); + }); + } + + private void addSpinnerListener (Spinner<Integer> spinner, Slider slider) { + spinner.getValueFactory().valueProperty().addListener((object, oldValue, newValue) -> { + slider.valueProperty().set(newValue.doubleValue()); + }); + } + + private void addSliderListener (Spinner<Integer> spinner, Slider slider) { + slider.valueProperty().addListener((object, oldValue, newValue) -> { + if(this.toggelGroup.getSelectedToggle() != null + && this.fixtureVM.getLightingMoodName().equals(((RadioButton)toggelGroup.getSelectedToggle()).getText())) { + this.updateFixtureDmxValues(); + if(!this.toggelGroup.getToggles().get(0).selectedProperty().get()) { + this.toggelGroup.getToggles().get(0).selectedProperty().set(true); + } + } + spinner.getValueFactory().setValue(newValue.intValue()); + }); + } + + private void loadGroups() { + this.groupNames.clear(); + this.groupRepositoryVM.groupsListProperty().forEach(groupVM -> { + this.groupNames.add(groupVM.getGroupName()); + }); + this.groupVM = this.groupRepositoryVM.getGroupVM(this.groupNames.get(0)); + this.comboBoxGroup.setItems(this.groupNames); + this.comboBoxGroup.setValue(this.groupNames.get(0)); + this.compositionRepositoryVM = this.groupVM.getCompositionRepositoryVM(); + } + + private void loadCompositions() { + this.compositionNames.clear(); + this.compositionRepositoryVM = this.groupVM.getCompositionRepositoryVM(); + this.compositionRepositoryVM.compositionListProperty().forEach(compositionVM -> { + this.compositionNames.add(compositionVM.getCompositionName()); + }); + if(this.compositionNames.size() > 0) { + this.compositionVM = this.compositionRepositoryVM.getComposition(this.compositionNames.get(0)); + this.comboBoxComposition.setItems(this.compositionNames); + this.comboBoxComposition.setValue(this.compositionNames.get(0)); + } + } + + private void loadFixtures() { + this.fixtureNames.clear(); + this.groupVM.getFixtureRepositoryVM().fixtureListProperty().forEach(fixtureVM -> { + this.fixtureNames.add(fixtureVM.getFixtureName()); + }); + this.fixtureVM = this.groupVM.getFixtureRepositoryVM().getFixtureVM(this.fixtureNames.get(0)); + this.lightMoodList.getItems().forEach(radioButton -> { + if(radioButton.getText().equals(this.fixtureVM.getLightingMoodName())) { + this.updateSliderDmxValues(this.fixtureVM.getDmxValuesVM()); + radioButton.selectedProperty().set(true); + } + }); + + this.comboBoxFixture.setItems(this.fixtureNames); + this.comboBoxFixture.setValue(this.fixtureNames.get(0)); + + } + + private void updateLightingMoodList() { + this.lightingMoods.clear(); + this.toggelGroup = new ToggleGroup(); + this.toggelGroup.selectedToggleProperty().addListener((object, oldValue, newValue) -> { + if(this.fixtureVM != null) { + RadioButton radioButton = (RadioButton) newValue; + if(!radioButton.getText().equals("Benutzerdefeniert")) { + LightingMoodVM lightingMoodVM = this.groupVM.getLightingMoodRepositoryVM().getLightingMood(radioButton.getText()); + this.updateSliderDmxValues(lightingMoodVM.getDmxValuesVM()); + this.updateFixtureDmxValues(lightingMoodVM.getDmxValuesVM()); + this.fixtureVM.setLightingMoodName(radioButton.getText()); + } else { + this.fixtureVM.setLightingMoodName(radioButton.getText()); + } + } + }); + + RadioButton userSpezified = new RadioButton("Benutzerdefeniert"); + userSpezified.setToggleGroup(toggelGroup); + this.lightingMoods.add(userSpezified); + this.groupVM.getLightingMoodRepositoryVM().lightingMoodListProperty().forEach(lightingMood -> { + RadioButton lightingMoodRadioButton = new RadioButton(lightingMood.getLightingMoodName()); + lightingMoodRadioButton.setToggleGroup(toggelGroup); + this.lightingMoods.add(lightingMoodRadioButton); + }); + } + + private void updateSliderDmxValues(DmxValuesVM dmxValuesVM) { + this.sliderMainIntensity.valueProperty().set(dmxValuesVM.getMainIntensity()); + this.sliderStrope.valueProperty().set(dmxValuesVM.getStrope()); + this.sliderRed.valueProperty().set(dmxValuesVM.getRed()); + this.sliderGreen.valueProperty().set(dmxValuesVM.getGreen()); + this.sliderBlue.valueProperty().set(dmxValuesVM.getBlue()); + } + + private void updateFixtureDmxValues() { + this.fixtureVM.getDmxValuesVM().setMainIntensity(this.sliderMainIntensity.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setStrope(this.sliderStrope.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setRed(this.sliderRed.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setGreen(this.sliderGreen.valueProperty().getValue().intValue()); + this.fixtureVM.getDmxValuesVM().setBlue(this.sliderBlue.valueProperty().getValue().intValue()); + } + + private void updateFixtureDmxValues(DmxValuesVM dmxValuesVM) { + this.fixtureVM.getDmxValuesVM().setMainIntensity(dmxValuesVM.getMainIntensity()); + this.fixtureVM.getDmxValuesVM().setStrope(dmxValuesVM.getStrope()); + this.fixtureVM.getDmxValuesVM().setRed(dmxValuesVM.getRed()); + this.fixtureVM.getDmxValuesVM().setGreen(dmxValuesVM.getGreen()); + this.fixtureVM.getDmxValuesVM().setBlue(dmxValuesVM.getBlue()); + } + + private void updateFixtureDmxValues(FixtureVM fixtureVM, DmxValuesVM dmxValuesVM) { + fixtureVM.getDmxValuesVM().setMainIntensity(dmxValuesVM.getMainIntensity()); + fixtureVM.getDmxValuesVM().setStrope(dmxValuesVM.getStrope()); + fixtureVM.getDmxValuesVM().setRed(dmxValuesVM.getRed()); + fixtureVM.getDmxValuesVM().setGreen(dmxValuesVM.getGreen()); + fixtureVM.getDmxValuesVM().setBlue(dmxValuesVM.getBlue()); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textfieldName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + private void updateFixtures() { + this.groupVM.getFixtureRepositoryVM().fixtureListProperty().forEach(fixtureVM -> { + if(this.compositionVM != null && this.compositionVM.getDmxValuesForFixture(fixtureVM.getFixtureName()) != null) { + this.updateFixtureDmxValues(fixtureVM, this.compositionVM.getDmxValuesForFixture(fixtureVM.getFixtureName())); + fixtureVM.setLightingMoodName("Benutzerdefeniert"); + } + }); + } + + public void setGroup(String name) { + this.comboBoxGroup.valueProperty().set(name); + this.groupVM = groupRepositoryVM.getGroupVM(name); + this.updateLightingMoodList(); + this.loadFixtures(); + } + + public void setComposition(String name) { + this.comboBoxComposition.valueProperty().set(name); + this.compositionVM = this.groupVM.getCompositionRepositoryVM().getComposition(this.comboBoxComposition.getValue()); + this.textfieldName.textProperty().set(this.compositionVM.getCompositionName()); + this.updateFixtures(); + this.updateSliderDmxValues(this.fixtureVM.getDmxValuesVM()); + } + +} diff --git a/src/lightControlSoftware/src/view/composition/mainPanel/CompositionMainPanel.fxml b/src/lightControlSoftware/src/view/composition/mainPanel/CompositionMainPanel.fxml new file mode 100644 index 0000000000000000000000000000000000000000..7532a43e3dabf3c3b1fcfa532fa48f01ff9f8b54 --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/mainPanel/CompositionMainPanel.fxml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.FlowPane?> +<?import javafx.scene.text.Font?> + +<AnchorPane prefHeight="350.0" prefWidth="880.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.composition.mainPanel.CompositionMainPanelController"> + <children> + <AnchorPane layoutX="5.0" layoutY="7.0" styleClass="section" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0"> + <children> + <BorderPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <center> + <ScrollPane fitToHeight="true" fitToWidth="true"> + <content> + <FlowPane fx:id="flowPaneCompositionList" /> + </content> + </ScrollPane> + </center> + <top> + <Button fx:id="buttonCreateNewCompositoin" mnemonicParsing="false" onAction="#createComposition" text="Neue Komposition erstellen" BorderPane.alignment="CENTER_LEFT"> + <BorderPane.margin> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </BorderPane.margin> + </Button> + </top> + </BorderPane> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </padding> + </AnchorPane> + <Label layoutX="20.0" styleClass="section-headline" text="Kompositionen" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> +</AnchorPane> diff --git a/src/lightControlSoftware/src/view/composition/mainPanel/CompositionMainPanelController.java b/src/lightControlSoftware/src/view/composition/mainPanel/CompositionMainPanelController.java new file mode 100644 index 0000000000000000000000000000000000000000..4e292b04187d44d588637a4e18e108ab083fba3f --- /dev/null +++ b/src/lightControlSoftware/src/view/composition/mainPanel/CompositionMainPanelController.java @@ -0,0 +1,95 @@ +package view.composition.mainPanel; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.image.Image; + +import java.io.IOException; + +import javafx.collections.ListChangeListener; +import javafx.event.ActionEvent; + +import javafx.scene.layout.FlowPane; +import javafx.stage.Stage; +import view.composition.CompositionListItem; +import view.composition.createPanel.CreateCompositionController; +import viewModel.KiwiViewModelHandler; +import viewModel.composition.CompositionRepositoryVM; +import viewModel.composition.CompositionVM; +import viewModel.group.GroupVM; + +public class CompositionMainPanelController { + @FXML + private FlowPane flowPaneCompositionList; + @FXML + private Button buttonCreateNewCompositoin; + + private KiwiViewModelHandler viewModelHandler; + private CompositionRepositoryVM compositionRepositoryVM; + private GroupVM groupVM; + + public void init(KiwiViewModelHandler viewModelHandler) { + this.viewModelHandler = viewModelHandler; + } + + // Event Listener on Button[#buttonCreateNewCompositoin].onAction + @FXML + public void createComposition(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../createPanel/CreateComposition.fxml")); + Parent createCompositionPanel = loader.load(); + CreateCompositionController createCompositionController = loader.getController(); + Scene scene = new Scene(createCompositionPanel); + Stage compositionDialog = new Stage(); + createCompositionController.init(compositionDialog, this.viewModelHandler); + createCompositionController.setGroup(this.groupVM.getGroupName()); + compositionDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + compositionDialog.setScene(scene); + compositionDialog.setTitle("Komposition erstellen"); + compositionDialog.showAndWait(); + createCompositionController = null; + loader = null; + } + + public void addCompositionToPane(CompositionVM compositionVM) { + this.flowPaneCompositionList.getChildren() + .add( + new CompositionListItem(compositionVM, this.groupVM, this.viewModelHandler)); + } + + public void setCompositionRepository(GroupVM groupVM) { + this.groupVM = groupVM; + this.compositionRepositoryVM = groupVM.getCompositionRepositoryVM(); + this.flowPaneCompositionList.getChildren().clear(); + this.compositionRepositoryVM.compositionListProperty().forEach(compositionVM -> { + addCompositionToPane(compositionVM); + }); + + this.compositionRepositoryVM.compositionListProperty().addListener((ListChangeListener.Change<? extends CompositionVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(compositionVM -> { + addCompositionToPane(compositionVM); + }); + + change.getRemoved().forEach(compositionVM -> { + int compositionListIndex = -1; + for(int i = 0; i < this.flowPaneCompositionList.getChildren().size(); i++) { + if(((CompositionListItem)this.flowPaneCompositionList + .getChildren() + .get(i)) + .getLightingMoodName() + .equals(compositionVM.getCompositionName())) { + compositionListIndex = i; + break; + } + } + if(compositionListIndex != -1) { + this.flowPaneCompositionList.getChildren().remove(compositionListIndex); + } + }); + } + }); + } +} diff --git a/src/lightControlSoftware/src/view/elements/ImageButton.java b/src/lightControlSoftware/src/view/elements/ImageButton.java new file mode 100644 index 0000000000000000000000000000000000000000..b4eff18745ab8fa4dba07251321e7829a8eccd04 --- /dev/null +++ b/src/lightControlSoftware/src/view/elements/ImageButton.java @@ -0,0 +1,27 @@ +package view.elements; + +import javafx.scene.control.Button; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; + +public class ImageButton extends Button{ + + Image icon; + ImageView imageView; + + public ImageButton(String imagePath) { + super(); + + this.icon = new Image(imagePath); + this.imageView = new ImageView(); + this.imageView.setImage(this.icon); + this.imageView.setFitHeight(25.0); + this.imageView.setFitWidth(25.0); + this.imageView.setPickOnBounds(true); + this.imageView.setPreserveRatio(true); + + this.setMnemonicParsing(false); + this.setStyle("-fx-background-color: none"); + this.setGraphic(imageView); + } +} diff --git a/src/lightControlSoftware/src/view/elements/NumberField.java b/src/lightControlSoftware/src/view/elements/NumberField.java new file mode 100644 index 0000000000000000000000000000000000000000..ea13991618afb1aca27d00f9903c20fddc8e0c3e --- /dev/null +++ b/src/lightControlSoftware/src/view/elements/NumberField.java @@ -0,0 +1,57 @@ +package view.elements; + +import javafx.beans.binding.Bindings; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.value.ObservableValue; +import javafx.scene.control.TextField; +import javafx.util.converter.NumberStringConverter; + +public class NumberField extends TextField { + + private IntegerProperty number; + + public NumberField () { + initSpellListener(); + this.number = new SimpleIntegerProperty(1); + Bindings.bindBidirectional(this.textProperty(), this.number, new NumberStringConverter()); + + } + + public final void initSpellListener() { + this.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> { + if (!newValue.matches("\\d*")) { + this.setText(newValue.replaceAll("[^\\d]", ""));/*The comma here "[^\\d,]" can be changed with the dot*/ + StringBuilder aus = new StringBuilder(); + aus.append(this.getText()); + boolean firstPointFound = false; + + for (int i = 0; i < aus.length(); i++) { + if (aus.charAt(i) == ',') {/*Change the , with . if you want the . to be the decimal separator*/ + if (!firstPointFound) { + firstPointFound = true; + } else { + aus.deleteCharAt(i); + } + } + } + newValue = aus.toString(); + this.setText(newValue); + } else { + this.setText(newValue); + } + }); + } + + public int getNumber() { + if(!this.getText().isEmpty()) { + return Integer.parseInt(this.getText()); + } else { + return 0; + } + } + + public IntegerProperty numberProperty() { + return this.number; + } +} diff --git a/src/lightControlSoftware/src/view/elements/ThreeStageButtonCallBack.java b/src/lightControlSoftware/src/view/elements/ThreeStageButtonCallBack.java new file mode 100644 index 0000000000000000000000000000000000000000..e7a05c6b0f36865546e240e4ae26d12026d1a81d --- /dev/null +++ b/src/lightControlSoftware/src/view/elements/ThreeStageButtonCallBack.java @@ -0,0 +1,5 @@ +package view.elements; + +public interface ThreeStageButtonCallBack { + public void callClicked(); +} diff --git a/src/lightControlSoftware/src/view/elements/ThreeStageSwitchButton.java b/src/lightControlSoftware/src/view/elements/ThreeStageSwitchButton.java new file mode 100644 index 0000000000000000000000000000000000000000..4aa4e4d4c4e5a3727869312a3b8f1b67e030d7c4 --- /dev/null +++ b/src/lightControlSoftware/src/view/elements/ThreeStageSwitchButton.java @@ -0,0 +1,98 @@ +package view.elements; + +import javafx.animation.FillTransition; +import javafx.animation.ParallelTransition; +import javafx.animation.TranslateTransition; +import javafx.application.Platform; +import javafx.beans.binding.Bindings; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.Pane; +import javafx.scene.paint.Color; +import javafx.scene.shape.Circle; +import javafx.scene.shape.Rectangle; +import javafx.util.Duration; +import viewModel.group.GroupVM.State; + +public class ThreeStageSwitchButton extends Pane{ + + private ObjectProperty<State> buttonState = new SimpleObjectProperty<>(State.OFF); + private TranslateTransition translateAnimation = new TranslateTransition(Duration.seconds(0.25)); + private FillTransition fillAnimation = new FillTransition(Duration.seconds(0.25)); + private ParallelTransition animation = new ParallelTransition(translateAnimation, fillAnimation); + private ThreeStageButtonCallBack callbackObject; + + public ThreeStageSwitchButton() { + super.setPrefWidth(100); + super.setPrefHeight(50); + + Rectangle background = new Rectangle(100,50); + background.widthProperty().bind(super.prefWidthProperty()); + background.heightProperty().bind(super.prefHeightProperty()); + background.arcWidthProperty().bind(super.prefHeightProperty()); + background.arcHeightProperty().bind(super.prefHeightProperty()); + background.setFill(Color.WHITE); + background.setStroke(Color.LIGHTGRAY); + + Circle trigger = new Circle(25); + trigger.radiusProperty().bind(Bindings.divide(super.prefHeightProperty(), 2.1)); + trigger.centerXProperty().bind(Bindings.divide(super.prefHeightProperty(), 2)); + trigger.centerYProperty().bind(Bindings.divide(super.prefHeightProperty(), 2)); + trigger.setFill(Color.WHITE); + trigger.setStroke(Color.LIGHTGRAY); + + translateAnimation.setNode(trigger); + fillAnimation.setShape(background); + + getChildren().addAll(background, trigger); + + buttonState.addListener((obs, oldState, newState) -> { + Platform.runLater(() -> { + switch (newState) { + case ON: + translateAnimation.setToX(background.getWidth() - background.getArcHeight()); + fillAnimation.setFromValue(oldState == State.OFF ? Color.WHITE : Color.GOLD); + fillAnimation.setToValue(Color.LIGHTGREEN); + break; + case MID: + translateAnimation.setToX((background.getWidth() - background.getArcHeight())/2); + fillAnimation.setFromValue(oldState == State.OFF ? Color.WHITE : Color.LIGHTGREEN); + fillAnimation.setToValue(Color.GOLD); + break; + case OFF: + translateAnimation.setToX(0); + fillAnimation.setFromValue(oldState == State.ON ? Color.LIGHTGREEN : Color.GOLD); + fillAnimation.setToValue(Color.WHITE); + break; + } + animation.play(); + }); + }); + + setOnMouseClicked(event -> { + switch (buttonState.get()) { + case OFF: + buttonState.set(State.ON); + break; + case MID: + case ON: + buttonState.set(State.OFF); + break; + } + }); + } + public void setCallback(ThreeStageButtonCallBack callbackObject) { + this.callbackObject = callbackObject; + this.removeEventHandler(MouseEvent.MOUSE_CLICKED, getOnMouseClicked()); + setOnMouseClicked(event -> { + Platform.runLater(() -> { + this.callbackObject.callClicked(); + }); + }); + } + + public ObjectProperty<State> buttonStateProperty() { + return this.buttonState; + } +} diff --git a/src/lightControlSoftware/src/view/fixture/FixtureGroupListCell.java b/src/lightControlSoftware/src/view/fixture/FixtureGroupListCell.java new file mode 100644 index 0000000000000000000000000000000000000000..6202167af8f7028fe25cdf2cb53985efd4dcbb87 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/FixtureGroupListCell.java @@ -0,0 +1,22 @@ +package view.fixture; + +import javafx.scene.control.ListCell; + +public class FixtureGroupListCell extends ListCell<FixturesGroupListItem> { + + public FixtureGroupListCell() { + super(); + } + + @Override + protected void updateItem(FixturesGroupListItem item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null) { + setGraphic(null); + } else { + setGraphic(item); + } + } + +} diff --git a/src/lightControlSoftware/src/view/fixture/FixtureListCell.java b/src/lightControlSoftware/src/view/fixture/FixtureListCell.java new file mode 100644 index 0000000000000000000000000000000000000000..35319d9e17c2e1e137e89a261f76fa07bf3c7fd0 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/FixtureListCell.java @@ -0,0 +1,22 @@ +package view.fixture; + +import javafx.scene.control.ListCell; + +public class FixtureListCell extends ListCell<FixturesListItem> { + + public FixtureListCell() { + super(); + } + + @Override + protected void updateItem(FixturesListItem item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null) { + setGraphic(null); + } else { + setGraphic(item); + } + } + +} diff --git a/src/lightControlSoftware/src/view/fixture/FixturesGroupListItem.java b/src/lightControlSoftware/src/view/fixture/FixturesGroupListItem.java new file mode 100644 index 0000000000000000000000000000000000000000..91e8e01cf5140a2d31c32b7b6affd5f248f35b7d --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/FixturesGroupListItem.java @@ -0,0 +1,138 @@ +package view.fixture; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import view.elements.ThreeStageSwitchButton; +import viewModel.fixture.FixtureGroupVM; +import viewModel.group.GroupVM.State; + + +public class FixturesGroupListItem extends AnchorPane{ + + private IntegerProperty groupId = new SimpleIntegerProperty(); + private StringProperty groupName = new SimpleStringProperty(); + private BooleanProperty fixtureInGroup = new SimpleBooleanProperty(false); + private BooleanProperty groupSelected = new SimpleBooleanProperty(false); + private FixtureGroupVM fixtureGroupVM; + + public FixturesGroupListItem(FixtureGroupVM fixtureGroupVM) { + this.fixtureGroupVM = fixtureGroupVM; + this.groupId.bind(this.fixtureGroupVM.groupIdProperty()); + this.groupName.bind(this.fixtureGroupVM.groupNameProperty()); + this.fixtureInGroup.bind(this.fixtureGroupVM.fixtureInGroupProperty()); + this.groupSelected.bind(this.fixtureGroupVM.groupSelectedProperty()); + + // style + setMaxHeight(50.0); + setMinHeight(50.0); + setPrefHeight(50.0); + VBox.setVgrow(this, Priority.ALWAYS); + VBox.setMargin(this, new Insets(5.0, 5.0, 5.0, 5.0)); + + VBox vBox = new VBox(); + vBox.setAlignment(Pos.CENTER_LEFT); + vBox.setLayoutX(7.0); + vBox.setLayoutY(2.0); + vBox.setMaxWidth(100.0); + AnchorPane.setBottomAnchor(vBox, 1.0); + AnchorPane.setLeftAnchor(vBox, 6.0); + AnchorPane.setTopAnchor(vBox, 1.0); + + Label lableGroupName = new Label(); + lableGroupName.textProperty().bind(groupName); + lableGroupName.setWrapText(true); + lableGroupName.getStyleClass().add("text-color-black"); + + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_RIGHT); + AnchorPane.setBottomAnchor(hBox, 0.0); + AnchorPane.setRightAnchor(hBox, 10.0); + AnchorPane.setTopAnchor(hBox, 0.0); + + + ThreeStageSwitchButton switchButton = new ThreeStageSwitchButton(); + switchButton.setMaxHeight(20.0); + switchButton.setMinHeight(20.0); + switchButton.setPrefHeight(20.0); + switchButton.setMaxWidth(45.0); + switchButton.setMinWidth(45.0); + switchButton.setPrefWidth(45.0); + switchButton.buttonStateProperty().set(this.fixtureInGroup.get() ? State.ON : State.OFF); + this.fixtureInGroup.addListener((object, oldValue, newValue) -> { + if(newValue) { + switchButton.buttonStateProperty().setValue(State.ON); + } else { + switchButton.buttonStateProperty().setValue(State.OFF); + } + }); + + switchButton.buttonStateProperty().addListener((object, oldValue, newValue) -> { + if(newValue == State.ON && !this.fixtureInGroup.get()) { + this.fixtureGroupVM.fixtureInGroupProperty().setValue(true); + } else if(newValue == State.OFF && this.fixtureInGroup.get()) { + this.fixtureGroupVM.fixtureInGroupProperty().setValue(false); + } + });; + + + + vBox.getChildren().add(lableGroupName); + hBox.getChildren().add(switchButton); + getChildren().addAll(vBox,hBox); + getStyleClass().addAll("list-item", "item-diselected"); + + + this.setOnMouseClicked(event -> { + if(!this.groupSelected.get()) { + this.fixtureGroupVM.setGroupSelected(true); + } + + }); + + this.groupSelected.addListener((object, oldValue, newValue) -> { + if(newValue) { + this.getStyleClass().add("item-selected"); + this.getStyleClass().remove("item-diselected"); + } else { + this.getStyleClass().add("item-diselected"); + this.getStyleClass().remove("item-selected"); + } + }); + + } + + public byte getGroupId() { + return (byte) this.groupId.get(); + } + + public String getGroupName() { + return this.groupName.get(); + } + + public boolean isGroupSelected() { + return this.groupSelected.get(); + } + + public IntegerProperty groupIdProperty() { + return this.groupId; + } + + public StringProperty groupNameProperty() { + return this.groupName; + } + + public BooleanProperty groupSelectedProperty() { + return this.groupSelected; + } +} diff --git a/src/lightControlSoftware/src/view/fixture/FixturesListItem.java b/src/lightControlSoftware/src/view/fixture/FixturesListItem.java new file mode 100644 index 0000000000000000000000000000000000000000..4198a15d3289b81510b21d09ce2682297097e0e4 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/FixturesListItem.java @@ -0,0 +1,122 @@ +package view.fixture; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import view.elements.ThreeStageSwitchButton; +import viewModel.fixture.FixtureVM; +import viewModel.group.GroupVM.State; + + +public class FixturesListItem extends AnchorPane{ + + private StringProperty fixtureName = new SimpleStringProperty(); + private BooleanProperty fixtureInGroup = new SimpleBooleanProperty(false); + private BooleanProperty fixtureSelected = new SimpleBooleanProperty(false); + private FixtureVM fixtureVM; + + public FixturesListItem(FixtureVM fixtureVM) { + this.fixtureVM = fixtureVM; + this.fixtureName.bind(this.fixtureVM.fixtureNameProperty()); + this.fixtureInGroup.bind(this.fixtureVM.fixtureInGroupProperty()); + this.fixtureSelected.bind(this.fixtureVM.fixtureSelectedProperty()); + + // style + setMaxHeight(50.0); + setMinHeight(50.0); + setPrefHeight(50.0); + VBox.setVgrow(this, Priority.ALWAYS); + VBox.setMargin(this, new Insets(5.0, 5.0, 5.0, 5.0)); + + VBox vBox = new VBox(); + vBox.setAlignment(Pos.CENTER_LEFT); + vBox.setLayoutX(7.0); + vBox.setLayoutY(2.0); + vBox.setMaxWidth(100.0); + AnchorPane.setBottomAnchor(vBox, 1.0); + AnchorPane.setLeftAnchor(vBox, 6.0); + AnchorPane.setTopAnchor(vBox, 1.0); + + Label lableGroupName = new Label(); + lableGroupName.textProperty().bind(this.fixtureName); + lableGroupName.setWrapText(true); + lableGroupName.getStyleClass().add("text-color-black"); + + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_RIGHT); + AnchorPane.setBottomAnchor(hBox, 0.0); + AnchorPane.setRightAnchor(hBox, 10.0); + AnchorPane.setTopAnchor(hBox, 0.0); + + + ThreeStageSwitchButton switchButton = new ThreeStageSwitchButton(); + switchButton.setMaxHeight(20.0); + switchButton.setMinHeight(20.0); + switchButton.setPrefHeight(20.0); + switchButton.setMaxWidth(45.0); + switchButton.setMinWidth(45.0); + switchButton.setPrefWidth(45.0); + switchButton.buttonStateProperty().set(this.fixtureInGroup.get() ? State.ON : State.OFF); + this.fixtureInGroup.addListener((object, oldValue, newValue) -> { + if(newValue) { + switchButton.buttonStateProperty().setValue(State.ON); + } else { + switchButton.buttonStateProperty().setValue(State.OFF); + } + }); + + switchButton.buttonStateProperty().addListener((object, oldValue, newValue) -> { + if(newValue == State.ON && !this.fixtureInGroup.get()) { + this.fixtureVM.fixtureInGroupProperty().setValue(true); + } else if(newValue == State.OFF && this.fixtureInGroup.get()) { + this.fixtureVM.fixtureInGroupProperty().setValue(false); + } + });; + + + + vBox.getChildren().add(lableGroupName); + hBox.getChildren().add(switchButton); + getChildren().addAll(vBox,hBox); + getStyleClass().addAll("list-item", "item-diselected"); + + + this.setOnMouseClicked(event -> { + if(!this.fixtureSelected.get()) { + this.fixtureVM.setFixtureSelected(true); + } + + }); + + this.fixtureSelected.addListener((object, oldValue, newValue) -> { + if(newValue) { + this.getStyleClass().add("item-selected"); + this.getStyleClass().remove("item-diselected"); + } else { + this.getStyleClass().add("item-diselected"); + this.getStyleClass().remove("item-selected"); + } + }); + } + + public String getFixtureName() { + return this.fixtureName.get(); + } + + public boolean isFixtureInGroup() { + return this.fixtureInGroup.get(); + } + + public FixtureVM getFixtureVM() { + return this.fixtureVM; + } + +} diff --git a/src/lightControlSoftware/src/view/fixture/createPanel/CreateFixture.fxml b/src/lightControlSoftware/src/view/fixture/createPanel/CreateFixture.fxml new file mode 100644 index 0000000000000000000000000000000000000000..468e84a23c7f97b4dd7488e05e29237fef9c3337 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/createPanel/CreateFixture.fxml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> +<?import view.elements.NumberField?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="270.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.fixture.createPanel.CreateFixtureController"> + <center> + <BorderPane BorderPane.alignment="CENTER"> + <top> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT"> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="10.0" /> + </VBox.margin> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <TextField fx:id="textboxName" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Startadresse*"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <NumberField fx:id="numberboxAdress" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </VBox.margin> + </HBox> + </children> + </VBox> + </top> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <AnchorPane styleClass="section" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="15.0"> + <children> + <VBox layoutX="7.0" layoutY="12.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <Button fx:id="buttonCreateGroup" mnemonicParsing="false" onAction="#createGroup" text="Neue Gruppe"> + <VBox.margin> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </VBox.margin> + </Button> + <ScrollPane fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS"> + <content> + <ListView fx:id="groupList"> + <styleClass> + <String fx:value="white-background" /> + <String fx:value="list-cell" /> + </styleClass> + </ListView> + </content> + </ScrollPane> + </children> + </VBox> + </children> + </AnchorPane> + <Label styleClass="section-headline" text="Gruppenzuordnung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="7.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> + </AnchorPane> + </center> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonCreateLamp" mnemonicParsing="false" onAction="#createLamp" text="Lampe hinzufügen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> + </BorderPane> + </center> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/fixture/createPanel/CreateFixtureController.java b/src/lightControlSoftware/src/view/fixture/createPanel/CreateFixtureController.java new file mode 100644 index 0000000000000000000000000000000000000000..dfa2887b5c5fae907402ccb005965f3a0509ccc1 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/createPanel/CreateFixtureController.java @@ -0,0 +1,175 @@ +package view.fixture.createPanel; + +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ListView; +import javafx.scene.control.TextField; +import javafx.scene.control.TextInputDialog; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.image.Image; + +import java.util.Optional; + +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import view.elements.NumberField; +import view.fixture.FixtureGroupListCell; +import view.fixture.FixturesGroupListItem; +import viewModel.KiwiViewModelHandler; +import viewModel.fixture.FixtureGroupRepositoryVM; +import viewModel.fixture.FixtureGroupVM; +import viewModel.fixture.FixtureRepositoryVM; +import viewModel.fixture.FixtureVM; + +public class CreateFixtureController { + @FXML + private BorderPane root; + @FXML + private TextField textboxName; + @FXML + private NumberField numberboxAdress; + @FXML + private Button buttonCreateGroup; + @FXML + private ListView<FixturesGroupListItem> groupList; + @FXML + private Button buttonCreateLamp; + @FXML + private Button buttonCancel; + + private Stage stage; + private FixtureRepositoryVM fixtureRepositoryVM; + private FixtureGroupRepositoryVM fixtureGroupRepositoryVM; + private ObservableList<FixturesGroupListItem> groups = FXCollections.observableArrayList(); + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + this.fixtureRepositoryVM = viewModelHandler.getFixtureRepositoryVM(); + this.fixtureGroupRepositoryVM = viewModelHandler.getFixtureGroupRepositoryVM(); + this.loadGroups(); + + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().addListener((ListChangeListener.Change<? extends FixtureGroupVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(fixtureGroupVM -> { + this.groups.add(new FixturesGroupListItem(fixtureGroupVM)); + }); + + change.getRemoved().forEach(groupVM -> { + int groupListIndex = -1; + for(int i = 0; i < this.groups.size(); i++) { + if(this.groups.get(i).getGroupName().equals(groupVM.getGroupName())) { + groupListIndex = i; + break; + } + } + if(groupListIndex != -1) { + this.groups.remove(groupListIndex); + } + }); + } + }); + + this.groupList.setItems(this.groups); + this.groupList.setCellFactory(param -> new FixtureGroupListCell()); + + } + + // Event Listener on Button[#buttonCreateGroup].onAction + @FXML + public void createGroup(ActionEvent event) { + TextInputDialog dialog = new TextInputDialog("Neue Gruppe"); + dialog.setTitle("Neue Gruppe"); + dialog.setHeaderText("Neue Gruppe erstellen"); + dialog.setContentText("Bitte geben Sie den Namen der neuen Gruppe ein:"); + Optional<String> result = dialog.showAndWait(); + result.ifPresent(name -> { + try { + this.fixtureGroupRepositoryVM.newGroup(name); + } catch (IllegalArgumentException e) { + Alert alert = new Alert(AlertType.ERROR); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler beim Erstellen einer Lampe."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + + }); + } + // Event Listener on Button[#buttonCreateLamp].onAction + @FXML + public void createLamp(ActionEvent event) { + if(this.isDataValid()) { + try { + this.fixtureRepositoryVM.newFixture(this.textboxName.getText(), this.numberboxAdress.getNumber()); + FixtureVM fixtureVM = this.fixtureRepositoryVM.getFixtureVM(this.textboxName.getText()); + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().forEach( fixtureGroup -> { + if(fixtureGroup.isFixtureInGroup()) { + fixtureGroup.addFixtureToGroup(fixtureVM); + } + }); + + + this.stage.close(); + } catch (IllegalArgumentException e) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Fehler"); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setHeaderText("Fehler beim Erstellen einer Lampe."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textboxName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else if(this.numberboxAdress.getText().isEmpty()) { + headerText = "Fehlerhafte Adresse."; + contentText = "Das Adressefeld darf nicht leer sein."; + } else if(this.numberboxAdress.getNumber() > 512 || this.numberboxAdress.getNumber() < 1) { + headerText = "Fehlerhafte Adresse."; + contentText = "Das Adresse der Lampe muss ziwschen 1 und 512 liegen."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + alert.setTitle("Warnung"); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + public void loadGroups() { + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().forEach(fixtureGroupVM -> { + this.groups.add(new FixturesGroupListItem(fixtureGroupVM)); + }); + } +} diff --git a/src/lightControlSoftware/src/view/fixture/editPanel/EditDeleteFixture.fxml b/src/lightControlSoftware/src/view/fixture/editPanel/EditDeleteFixture.fxml new file mode 100644 index 0000000000000000000000000000000000000000..71046924711cee7d2fb3c9d8c01e6ecb400046c3 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/editPanel/EditDeleteFixture.fxml @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> +<?import view.elements.NumberField?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="300.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.fixture.editPanel.EditDeleteFixtureController"> + <center> + <BorderPane BorderPane.alignment="CENTER"> + <top> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Lampe"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <VBox alignment="CENTER_LEFT" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="45.0" AnchorPane.topAnchor="0.0"> + <children> + <AnchorPane> + <children> + <ComboBox fx:id="comboboxFixture" onAction="#selectFixture" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + </VBox> + <Button fx:id="buttonDelete" mnemonicParsing="false" onAction="#deleteFixture" style="-fx-background-color: none;" AnchorPane.rightAnchor="0.0"> + <graphic> + <ImageView fitHeight="20.0" fitWidth="20.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../../../../ressourcen/images/Delete.png" /> + </image> + </ImageView> + </graphic> + </Button> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="10.0" /> + </VBox.margin> + </HBox> + <HBox alignment="CENTER_LEFT"> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </VBox.margin> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <TextField fx:id="textboxName" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Startadresse*"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <NumberField fx:id="numberboxAdress" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </VBox.margin> + </HBox> + </children> + </VBox> + </top> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <AnchorPane styleClass="section" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="15.0"> + <children> + <VBox layoutX="7.0" layoutY="12.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <Button fx:id="buttonCreateGroup" mnemonicParsing="false" onAction="#createGroup" text="Neue Gruppe"> + <VBox.margin> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </VBox.margin> + </Button> + <ScrollPane fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS"> + <content> + <ListView fx:id="groupList"> + <styleClass> + <String fx:value="white-background" /> + <String fx:value="list-cell" /> + </styleClass> + </ListView> + </content> + </ScrollPane> + </children> + </VBox> + </children> + </AnchorPane> + <Label styleClass="section-headline" text="Gruppenzuordnung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="7.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> + </AnchorPane> + </center> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#save" text="Speichern"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> + </BorderPane> + </center> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/fixture/editPanel/EditDeleteFixtureController.java b/src/lightControlSoftware/src/view/fixture/editPanel/EditDeleteFixtureController.java new file mode 100644 index 0000000000000000000000000000000000000000..b0c18724979e8aa83a44061b9cb703a661192249 --- /dev/null +++ b/src/lightControlSoftware/src/view/fixture/editPanel/EditDeleteFixtureController.java @@ -0,0 +1,236 @@ +package view.fixture.editPanel; + +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.TextField; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.image.Image; + +import java.util.Optional; + +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; + +import javafx.scene.control.ListView; + +import javafx.scene.control.ComboBox; + +import view.elements.NumberField; +import view.fixture.FixtureGroupListCell; +import view.fixture.FixturesGroupListItem; +import viewModel.KiwiViewModelHandler; +import viewModel.fixture.FixtureGroupRepositoryVM; +import viewModel.fixture.FixtureGroupVM; +import viewModel.fixture.FixtureRepositoryVM; +import viewModel.fixture.FixtureVM; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; + +public class EditDeleteFixtureController { + @FXML + private BorderPane root; + @FXML + private ComboBox<String> comboboxFixture; + @FXML + private Button buttonDelete; + @FXML + private TextField textboxName; + @FXML + private NumberField numberboxAdress; + @FXML + private Button buttonCreateGroup; + @FXML + private ListView<FixturesGroupListItem> groupList; + @FXML + private Button buttonSave; + @FXML + private Button buttonCancel; + + private Stage stage; + private FixtureRepositoryVM fixtureRepositoryVM; + private FixtureGroupRepositoryVM fixtureGroupRepositoryVM; + private FixtureVM fixtureVM; + private ObservableList<String> fixtureNames = FXCollections.observableArrayList(); + private ObservableList<FixturesGroupListItem> groups = FXCollections.observableArrayList(); + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.fixtureRepositoryVM = viewModelHandler.getFixtureRepositoryVM(); + this.fixtureGroupRepositoryVM = viewModelHandler.getFixtureGroupRepositoryVM(); + + this.loadFixtures(); + this.loadGroups(); + + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().addListener((ListChangeListener.Change<? extends FixtureGroupVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(fixtureGroupVM -> { + this.groups.add(new FixturesGroupListItem(fixtureGroupVM)); + }); + + change.getRemoved().forEach(groupVM -> { + int groupListIndex = -1; + for(int i = 0; i < this.groups.size(); i++) { + if(this.groups.get(i).getGroupName().equals(groupVM.getGroupName())) { + groupListIndex = i; + break; + } + } + if(groupListIndex != -1) { + this.groups.remove(groupListIndex); + } + }); + } + }); + this.groupList.setItems(this.groups); + this.groupList.setCellFactory(param -> new FixtureGroupListCell()); + this.updateFixturesGroups(); + } + + // Event Listener on ComboBox[#comboboxFixture].onAction + @FXML + public void selectFixture(ActionEvent event) { + if(!(this.comboboxFixture.getValue() == null)) { + this.fixtureVM = fixtureRepositoryVM.getFixtureVM(this.comboboxFixture.getValue()); + this.textboxName.setText(this.fixtureVM.getFixtureName()); + this.numberboxAdress.setText(String.valueOf(this.fixtureVM.getFixtureAddress())); + this.updateFixturesGroups(); + } + + } + // Event Listener on Button[#buttonDelete].onAction + @FXML + public void deleteFixture(ActionEvent event) { + Alert alert = new Alert(AlertType.CONFIRMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Lampe l�schen"); + alert.setHeaderText(String.format("Sind Sie sicher, dass Sie die Lampe %s l�schen m�chten", this.fixtureVM.getFixtureName())); + ButtonType buttonDelete = new ButtonType("Lampe l�schen"); + ButtonType buttonCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + alert.getButtonTypes().setAll(buttonDelete, buttonCancel); + Optional<ButtonType> result = alert.showAndWait(); + if (result.orElseThrow() == buttonDelete) { + this.fixtureRepositoryVM.deleteFixture(this.fixtureVM.getFixtureName()); + this.loadFixtures(); + } + } + // Event Listener on Button[#buttonCreateGroup].onAction + @FXML + public void createGroup(ActionEvent event) { + // TODO Autogenerated + } + // Event Listener on Button[#buttonCreateLamp].onAction + @FXML + public void save(ActionEvent event) { + if(this.isDataValid()) { + this.fixtureVM.setFixtureName(this.textboxName.getText()); + this.fixtureVM.setFixtureAddress(this.numberboxAdress.getNumber()); + + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().forEach(fixtureGroup -> { + boolean fixtureInGroup = fixtureGroup.getFixtureRepositoryVM() + .fixtureListProperty() + .stream() + .filter(fixtureVM -> fixtureVM.getFixtureName().equals(this.fixtureVM.getFixtureName())) + .findFirst() + .isPresent(); + + if(fixtureInGroup && !fixtureGroup.isFixtureInGroup()) { + fixtureGroup.removeFixtureFromGroup(this.fixtureVM); + } else if (!fixtureInGroup && fixtureGroup.isFixtureInGroup()){ + fixtureGroup.addFixtureToGroup(this.fixtureVM); + } + }); + this.stage.close(); + } + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + + private boolean isDataValid () { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textboxName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Die Namensfeld darf nicht leer sein."; + } else if(nameAllreadyExist(this.textboxName.getText())) { + headerText = "Fehlerhafter Name."; + contentText = "Der Name ist bereits in Benutzung."; + } else if(this.numberboxAdress.getText().isEmpty()) { + headerText = "Fehlerhafte Adresse."; + contentText = "Die Adressefeld darf nicht leer sein."; + } else if(this.numberboxAdress.getNumber() > 512 || this.numberboxAdress.getNumber() < 1) { + headerText = "Fehlerhafte Adresse."; + contentText = "Die Adresse der Lampe muss ziwschen 1 und 512 liegen."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + private boolean nameAllreadyExist(String name) { + boolean nameExist = false; + if(!this.fixtureVM.getFixtureName().equals(name) && + this.fixtureNames.stream() + .filter(fixtureName -> fixtureName.equals(name)) + .count() > 0){ + nameExist = true; + } + + return nameExist; + } + + private void loadGroups() { + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().forEach(fixtureGroupVM -> { + this.groups.add(new FixturesGroupListItem(fixtureGroupVM)); + }); + } + + private void loadFixtures() { + this.fixtureNames.clear(); + this.fixtureRepositoryVM.fixturesRepositoryProperty().forEach(fixtureVM -> { + this.fixtureNames.add(fixtureVM.getFixtureName()); + }); + this.fixtureVM = fixtureRepositoryVM.getFixtureVM(this.fixtureNames.get(0)); + this.comboboxFixture.setItems(this.fixtureNames); + this.comboboxFixture.setValue(this.fixtureNames.get(0)); + this.textboxName.setText(this.fixtureVM.getFixtureName()); + this.numberboxAdress.setText(String.valueOf(this.fixtureVM.getFixtureAddress())); + } + + private void updateFixturesGroups() { + this.fixtureGroupRepositoryVM.fixtureGroupsListProperty().forEach(fixtureGroup -> { + boolean fixtureInGroup = fixtureGroup.getFixtureRepositoryVM() + .fixtureListProperty() + .stream() + .filter(fixtureVM -> fixtureVM.getFixtureName().equals(this.fixtureVM.getFixtureName())) + .findFirst() + .isPresent(); + + if(fixtureInGroup) { + fixtureGroup.setFixtureInGroup(true); + } else { + fixtureGroup.setFixtureInGroup(false); + } + }); + } + +} diff --git a/src/lightControlSoftware/src/view/group/GroupListCell.java b/src/lightControlSoftware/src/view/group/GroupListCell.java new file mode 100644 index 0000000000000000000000000000000000000000..d252764ab50ac447d3369fc2b772cd5230aa35d0 --- /dev/null +++ b/src/lightControlSoftware/src/view/group/GroupListCell.java @@ -0,0 +1,22 @@ +package view.group; + +import javafx.scene.control.ListCell; + +public class GroupListCell extends ListCell<GroupListItem> { + + public GroupListCell() { + super(); + } + + @Override + protected void updateItem(GroupListItem item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null) { + setGraphic(null); + } else { + setGraphic(item); + } + } + +} diff --git a/src/lightControlSoftware/src/view/group/GroupListItem.java b/src/lightControlSoftware/src/view/group/GroupListItem.java new file mode 100644 index 0000000000000000000000000000000000000000..e6bbb228bdd8f0d464379fa3fe4e1153bbe52151 --- /dev/null +++ b/src/lightControlSoftware/src/view/group/GroupListItem.java @@ -0,0 +1,183 @@ +package view.group; + +import java.io.IOException; +import java.util.Optional; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.image.Image; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import view.elements.ImageButton; +import view.elements.ThreeStageSwitchButton; +import view.group.editPanel.EditDeleteGroupController; +import viewModel.KiwiViewModelHandler; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; +import viewModel.group.GroupVM.State; + + +public class GroupListItem extends AnchorPane{ + + private IntegerProperty groupId = new SimpleIntegerProperty(); + private StringProperty groupName = new SimpleStringProperty(); + private ObjectProperty<State> groupState = new SimpleObjectProperty<>(State.OFF); + private BooleanProperty groupSelected = new SimpleBooleanProperty(false); + private GroupVM groupVM; + private GroupRepositoryVM groupRepositoryVM; + + public GroupListItem(GroupVM groupVM, KiwiViewModelHandler viewModelHandler) { + this.groupVM = groupVM; + this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); + this.groupId.bind(this.groupVM.groupIdProperty()); + this.groupName.bind(this.groupVM.groupNameProperty()); + this.groupState.bindBidirectional(this.groupVM.groupStateProperty());; + this.groupSelected.bind(this.groupVM.groupSelectedProperty()); + + // style + setMaxHeight(50.0); + setMinHeight(50.0); + setPrefHeight(50.0); + VBox.setVgrow(this, Priority.ALWAYS); + VBox.setMargin(this, new Insets(5.0, 5.0, 5.0, 5.0)); + + VBox vBox = new VBox(); + vBox.setAlignment(Pos.CENTER_LEFT); + vBox.setLayoutX(7.0); + vBox.setLayoutY(2.0); + vBox.setMaxWidth(100.0); + AnchorPane.setBottomAnchor(vBox, 1.0); + AnchorPane.setLeftAnchor(vBox, 6.0); + AnchorPane.setTopAnchor(vBox, 1.0); + + Label lableGroupName = new Label(); + lableGroupName.textProperty().bind(groupName); + lableGroupName.setWrapText(true); + lableGroupName.getStyleClass().add("text-color-black"); + + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_RIGHT); + AnchorPane.setBottomAnchor(hBox, 0.0); + AnchorPane.setRightAnchor(hBox, 0.0); + AnchorPane.setTopAnchor(hBox, 0.0); + + ThreeStageSwitchButton switchButton = new ThreeStageSwitchButton(); + switchButton.setMaxHeight(20.0); + switchButton.setMinHeight(20.0); + switchButton.setPrefHeight(20.0); + switchButton.setMaxWidth(45.0); + switchButton.setMinWidth(45.0); + switchButton.setPrefWidth(45.0); + switchButton.buttonStateProperty().bindBidirectional(this.groupState); + + ImageButton buttonEditGroup = new ImageButton("images/Edit.png"); + buttonEditGroup.setOnAction(event -> { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../group/editPanel/EditDeleteGroup.fxml")); + Parent editDeleteGroupPanel; + editDeleteGroupPanel = loader.load(); + EditDeleteGroupController editDeleteGroupController = loader.getController(); + Scene scene = new Scene(editDeleteGroupPanel); + Stage groupDialog = new Stage(); + editDeleteGroupController.init(groupDialog, viewModelHandler); + editDeleteGroupController.setGroup(groupVM); + groupDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + groupDialog.setScene(scene); + groupDialog.setTitle("Gruppe �ndern/l�schen"); + groupDialog.showAndWait(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + }); + + ImageButton buttonDeleteGroup = new ImageButton("images/Delete.png"); + buttonDeleteGroup.setOnAction(event -> { + Alert alert = new Alert(AlertType.CONFIRMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Gruppe l�schen"); + alert.setHeaderText(String.format("Sind Sie sicher, dass Sie die Gruppe %s l�schen m�chten", this.getGroupName())); + ButtonType buttonDelete = new ButtonType("Gruppe l�schen"); + ButtonType buttonCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + alert.getButtonTypes().setAll(buttonDelete, buttonCancel); + Optional<ButtonType> result = alert.showAndWait(); + if (result.orElseThrow() == buttonDelete) { + groupRepositoryVM.deleteGroup(this.getGroupName()); + } + }); + + + vBox.getChildren().add(lableGroupName); + hBox.getChildren().addAll(switchButton, buttonEditGroup, buttonDeleteGroup); + getChildren().addAll(vBox,hBox); + getStyleClass().addAll("list-item", "item-diselected"); + + + this.setOnMouseClicked(event -> { + if(!this.groupSelected.get()) { + this.groupVM.setGroupSelected(true); + } + + }); + + this.groupSelected.addListener((object, oldValue, newValue) -> { + if(newValue) { + this.getStyleClass().add("item-selected"); + this.getStyleClass().remove("item-diselected"); + } else { + this.getStyleClass().add("item-diselected"); + this.getStyleClass().remove("item-selected"); + } + }); + + } + + public byte getGroupId() { + return (byte) this.groupId.get(); + } + + public String getGroupName() { + return this.groupName.get(); + } + + public boolean isGroupSelected() { + return this.groupSelected.get(); + } + + public void selectedGroup() { + this.groupVM.groupSelectedProperty().set(true); + } + + public IntegerProperty groupIdProperty() { + return this.groupId; + } + + public StringProperty groupNameProperty() { + return this.groupName; + } + + public BooleanProperty groupSelectedProperty() { + return this.groupSelected; + } +} diff --git a/src/lightControlSoftware/src/view/group/createPanel/CreateGroup.fxml b/src/lightControlSoftware/src/view/group/createPanel/CreateGroup.fxml new file mode 100644 index 0000000000000000000000000000000000000000..5f34aaa79d922ba5376752f323e095c8c8e7e89e --- /dev/null +++ b/src/lightControlSoftware/src/view/group/createPanel/CreateGroup.fxml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="270.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.group.createPanel.CreateGroupController"> + <center> + <BorderPane BorderPane.alignment="CENTER"> + <top> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT"> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="10.0" /> + </VBox.margin> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <TextField fx:id="textboxName" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + </children> + </VBox> + </top> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <AnchorPane styleClass="section" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="15.0"> + <children> + <VBox layoutX="7.0" layoutY="12.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <ScrollPane fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS"> + <content> + <ListView fx:id="groupList"> + <styleClass> + <String fx:value="white-background" /> + <String fx:value="list-cell" /> + </styleClass> + </ListView> + </content> + </ScrollPane> + </children> + </VBox> + </children> + </AnchorPane> + <Label styleClass="section-headline" text="Lampenzuordnung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="7.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> + </AnchorPane> + </center> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonCreateGroup" mnemonicParsing="false" onAction="#createGroup" text="Gruppe hinzufügen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> + </BorderPane> + </center> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/group/createPanel/CreateGroupController.java b/src/lightControlSoftware/src/view/group/createPanel/CreateGroupController.java new file mode 100644 index 0000000000000000000000000000000000000000..98224e18f8008d75e3b9f9603ea78ba9f72656a0 --- /dev/null +++ b/src/lightControlSoftware/src/view/group/createPanel/CreateGroupController.java @@ -0,0 +1,137 @@ +package view.group.createPanel; + +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; + +import javafx.scene.control.TextField; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.image.Image; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; + +import javafx.scene.control.ListView; + +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import view.fixture.FixtureListCell; +import view.fixture.FixturesListItem; +import viewModel.KiwiViewModelHandler; +import viewModel.fixture.FixtureRepositoryVM; +import viewModel.fixture.FixtureVM; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; + +public class CreateGroupController { + @FXML + private BorderPane root; + @FXML + private TextField textboxName; + @FXML + private ListView<FixturesListItem> groupList; + @FXML + private Button buttonCreateGroup; + @FXML + private Button buttonCancel; + + private FixtureRepositoryVM fixtureRepositoryVM; + private GroupRepositoryVM groupRepositoryVM; + private ObservableList<FixturesListItem> fixtures = FXCollections.observableArrayList(); + private Stage stage; + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.fixtureRepositoryVM = viewModelHandler.getFixtureRepositoryVM(); + this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); + this.loadFixtures(); + + this.fixtureRepositoryVM.fixtureListProperty().addListener((ListChangeListener.Change<? extends FixtureVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(fixtureVM -> { + this.fixtures.add(new FixturesListItem(fixtureVM)); + }); + + change.getRemoved().forEach(fixtureVM -> { + int fixtureListIndex = -1; + for(int i = 0; i < this.fixtures.size(); i++) { + if(this.fixtures.get(i).getFixtureName().equals(fixtureVM.getFixtureName())) { + fixtureListIndex = i; + break; + } + } + if(fixtureListIndex != -1) { + this.fixtures.remove(fixtureListIndex); + } + }); + } + }); + + + this.groupList.setItems(this.fixtures); + this.groupList.setCellFactory(param -> new FixtureListCell()); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textboxName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + // Event Listener on Button[#buttonCreateGroup].onAction + @FXML + public void createGroup(ActionEvent event) { + if(isDataValid()) { + try { + this.groupRepositoryVM.newGroup(this.textboxName.getText()); + GroupVM groupVM = this.groupRepositoryVM.getGroupVM(this.textboxName.getText()); + this.fixtures.forEach(fixtureListItem -> { + if(fixtureListItem.isFixtureInGroup()) { + groupVM.addFixture(fixtureListItem.getFixtureVM()); + } + }); + this.stage.close(); + } catch (IllegalArgumentException e) { + Alert alert = new Alert(AlertType.ERROR); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler beim Erstellen einer Gruppe."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + + public void loadFixtures() { + this.fixtureRepositoryVM.fixturesRepositoryProperty().forEach(fixtureVM -> { + this.fixtures.add(new FixturesListItem(fixtureVM)); + }); + } + +} diff --git a/src/lightControlSoftware/src/view/group/editPanel/EditDeleteGroup.fxml b/src/lightControlSoftware/src/view/group/editPanel/EditDeleteGroup.fxml new file mode 100644 index 0000000000000000000000000000000000000000..5be9662b55649b46bdeb94837bdd0dd20ce971a5 --- /dev/null +++ b/src/lightControlSoftware/src/view/group/editPanel/EditDeleteGroup.fxml @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="320.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.group.editPanel.EditDeleteGroupController"> + <center> + <BorderPane BorderPane.alignment="CENTER"> + <top> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT"> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="10.0" /> + </VBox.margin> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Gruppe"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <VBox alignment="BOTTOM_LEFT" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="45.0"> + <children> + <AnchorPane> + <children> + <ComboBox fx:id="comboboxGroup" onAction="#selectGroup" prefWidth="150.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + </VBox> + <Button fx:id="buttonDelete" mnemonicParsing="false" onAction="#deleteGroup" style="-fx-background-color: none;" AnchorPane.rightAnchor="0.0"> + <graphic> + <ImageView fitHeight="20.0" fitWidth="20.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../../../../ressourcen/images/Delete.png" /> + </image> + </ImageView> + </graphic> + </Button> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*"> + <HBox.margin> + <Insets left="5.0" right="15.0" /> + </HBox.margin> + </Label> + <HBox HBox.hgrow="ALWAYS"> + <children> + <AnchorPane HBox.hgrow="ALWAYS"> + <children> + <TextField fx:id="textboxName" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" /> + </children> + </AnchorPane> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + </children> + <VBox.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </VBox.margin> + </HBox> + </children> + </VBox> + </top> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <AnchorPane styleClass="section" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="15.0"> + <children> + <VBox layoutX="7.0" layoutY="12.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <ScrollPane fitToHeight="true" fitToWidth="true" VBox.vgrow="ALWAYS"> + <content> + <ListView fx:id="groupList"> + <styleClass> + <String fx:value="white-background" /> + <String fx:value="list-cell" /> + </styleClass> + </ListView> + </content> + </ScrollPane> + </children> + </VBox> + </children> + </AnchorPane> + <Label styleClass="section-headline" text="Lampenzuordnung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="7.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> + </AnchorPane> + </center> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonCreateGroup" mnemonicParsing="false" onAction="#createGroup" text="Speichern"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> + </BorderPane> + </center> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/group/editPanel/EditDeleteGroupController.java b/src/lightControlSoftware/src/view/group/editPanel/EditDeleteGroupController.java new file mode 100644 index 0000000000000000000000000000000000000000..f5202bf004d5c8c8fc88c20056bb6da75ad606e6 --- /dev/null +++ b/src/lightControlSoftware/src/view/group/editPanel/EditDeleteGroupController.java @@ -0,0 +1,214 @@ +package view.group.editPanel; + +import javafx.fxml.FXML; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.TextField; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.image.Image; + +import java.util.Optional; + +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; + +import javafx.scene.control.ListView; + +import javafx.scene.control.ComboBox; + +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import view.fixture.FixtureListCell; +import view.fixture.FixturesListItem; +import viewModel.KiwiViewModelHandler; +import viewModel.fixture.FixtureRepositoryVM; +import viewModel.fixture.FixtureVM; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; + +public class EditDeleteGroupController { + @FXML + private BorderPane root; + @FXML + private ComboBox<String> comboboxGroup; + @FXML + private Button buttonDelete; + @FXML + private TextField textboxName; + @FXML + private ListView<FixturesListItem> groupList; + @FXML + private Button buttonCreateGroup; + @FXML + private Button buttonCancel; + + private FixtureRepositoryVM fixtureRepositoryVM; + private GroupRepositoryVM groupRepositoryVM; + private ObservableList<FixturesListItem> fixtures = FXCollections.observableArrayList(); + private ObservableList<String> groupNames = FXCollections.observableArrayList(); + private Stage stage; + private GroupVM groupVM; + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.fixtureRepositoryVM = viewModelHandler.getFixtureRepositoryVM(); + this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); + this.loadGroups(); + this.loadFixtures(); + + this.fixtureRepositoryVM.fixtureListProperty().addListener((ListChangeListener.Change<? extends FixtureVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(fixtureVM -> { + this.fixtures.add(new FixturesListItem(fixtureVM)); + }); + + change.getRemoved().forEach(fixtureVM -> { + int fixtureListIndex = -1; + for(int i = 0; i < this.fixtures.size(); i++) { + if(this.fixtures.get(i).getFixtureName().equals(fixtureVM.getFixtureName())) { + fixtureListIndex = i; + break; + } + } + if(fixtureListIndex != -1) { + this.fixtures.remove(fixtureListIndex); + } + }); + } + }); + + + this.groupList.setItems(this.fixtures); + this.groupList.setCellFactory(param -> new FixtureListCell()); + this.updateFixtures(); + } + + // Event Listener on ComboBox[#comboboxGroup].onAction + @FXML + public void selectGroup(ActionEvent event) { + if(!(this.comboboxGroup.getValue() == null)) { + this.groupVM = groupRepositoryVM.getGroupVM(this.comboboxGroup.getValue()); + this.textboxName.setText(this.groupVM.getGroupName()); + this.updateFixtures(); + } + } + // Event Listener on Button[#buttonDelete].onAction + @FXML + public void deleteGroup(ActionEvent event) { + Alert alert = new Alert(AlertType.CONFIRMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Gruppe l�schen"); + alert.setHeaderText(String.format("Sind Sie sicher, dass Sie die Gruppe %s l�schen m�chten", this.groupVM.getGroupName())); + ButtonType buttonDelete = new ButtonType("Gruppe l�schen"); + ButtonType buttonCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + alert.getButtonTypes().setAll(buttonDelete, buttonCancel); + Optional<ButtonType> result = alert.showAndWait(); + if (result.orElseThrow() == buttonDelete) { + this.groupRepositoryVM.deleteGroup(this.textboxName.getText()); + this.loadGroups(); + } + } + // Event Listener on Button[#buttonCreateGroup].onAction + @FXML + public void createGroup(ActionEvent event) { + if(this.isDataValid()) { + this.groupVM.setGroupName(this.textboxName.getText()); + + this.fixtureRepositoryVM.fixtureListProperty().forEach(fixtureVM -> { + if(this.groupVM.isFixtureInGroup(fixtureVM.getFixtureName()) && !fixtureVM.isFixtureInGroup()) { + this.groupVM.removeFixture(fixtureVM); + } else if (!this.groupVM.isFixtureInGroup(fixtureVM.getFixtureName()) && fixtureVM.isFixtureInGroup()){ + this.groupVM.addFixture(fixtureVM); + } + }); + this.stage.close(); + } + + + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textboxName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else if(nameAllreadyExist(this.textboxName.getText())) { + headerText = "Fehlerhafter Name."; + contentText = "Der Name ist bereits in Benutzung."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + private boolean nameAllreadyExist(String name) { + boolean nameExist = false; + if(!this.groupVM.getGroupName().equals(name) && + this.groupNames.stream() + .filter(groupName -> groupName.equals(name)) + .count() > 0){ + nameExist = true; + } + + return nameExist; + } + + private void loadGroups() { + this.groupNames.clear(); + this.groupRepositoryVM.groupsListProperty().forEach(groupVM -> { + this.groupNames.add(groupVM.getGroupName()); + }); + this.groupVM = groupRepositoryVM.getGroupVM(this.groupNames.get(0)); + this.comboboxGroup.setItems(this.groupNames); + this.comboboxGroup.setValue(this.groupNames.get(0)); + this.textboxName.setText(this.groupVM.getGroupName()); + } + + public void loadFixtures() { + this.fixtureRepositoryVM.fixturesRepositoryProperty().forEach(fixtureVM -> { + this.fixtures.add(new FixturesListItem(fixtureVM)); + }); + } + + public void updateFixtures() { + this.fixtureRepositoryVM.fixtureListProperty().forEach(fixtureVM -> { + if(this.groupVM.isFixtureInGroup(fixtureVM.getFixtureName())) { + fixtureVM.setFixtureInGroup(true); + } else { + fixtureVM.setFixtureInGroup(false); + } + }); + } + + public void setGroup(GroupVM groupVM) { + comboboxGroup.valueProperty().set(groupVM.getGroupName()); + this.groupVM = groupRepositoryVM.getGroupVM(this.comboboxGroup.getValue()); + this.textboxName.setText(this.groupVM.getGroupName()); + this.updateFixtures(); + } + +} diff --git a/src/lightControlSoftware/src/view/group/mainPanel/GroupMainPanel.fxml b/src/lightControlSoftware/src/view/group/mainPanel/GroupMainPanel.fxml new file mode 100644 index 0000000000000000000000000000000000000000..cfeedecbf3429b66c5ce1e7fb2ca138fd2c2bb76 --- /dev/null +++ b/src/lightControlSoftware/src/view/group/mainPanel/GroupMainPanel.fxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import java.lang.String?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ListView?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.text.Font?> + +<AnchorPane prefHeight="580.0" prefWidth="300.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.group.mainPanel.GroupMainPanelController"> + <children> + <AnchorPane layoutX="5.0" layoutY="7.0" styleClass="section" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0"> + <children> + <BorderPane AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <center> + <ScrollPane fitToHeight="true" fitToWidth="true"> + <content> + <ListView fx:id="groupsList" prefHeight="200.0" prefWidth="200.0"> + <styleClass> + <String fx:value="list-cell" /> + <String fx:value="white-background" /> + </styleClass></ListView> + </content> + </ScrollPane> + </center> + <top> + <Button fx:id="buttonCreateNewGroupe" mnemonicParsing="false" onAction="#createGroup" text="Neue Gruppe erstellen" BorderPane.alignment="CENTER_LEFT"> + <BorderPane.margin> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </BorderPane.margin> + </Button> + </top> + </BorderPane> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </padding> + </AnchorPane> + <Label layoutX="20.0" styleClass="section-headline" text="Gruppen" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> +</AnchorPane> diff --git a/src/lightControlSoftware/src/view/group/mainPanel/GroupMainPanelController.java b/src/lightControlSoftware/src/view/group/mainPanel/GroupMainPanelController.java new file mode 100644 index 0000000000000000000000000000000000000000..45439ba6e7138a08586ceb4b20f92ff9541cd61e --- /dev/null +++ b/src/lightControlSoftware/src/view/group/mainPanel/GroupMainPanelController.java @@ -0,0 +1,100 @@ +package view.group.mainPanel; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.image.Image; +import javafx.stage.Stage; +import view.composition.mainPanel.CompositionMainPanelController; +import view.group.GroupListCell; +import view.group.GroupListItem; +import view.group.createPanel.CreateGroupController; +import view.lightingMood.mainPanel.LightingMoodMainPanelController; +import javafx.scene.control.Button; +import java.io.IOException; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.scene.control.ListView; +import viewModel.KiwiViewModelHandler; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; + +public class GroupMainPanelController { + @FXML + private ListView<GroupListItem> groupsList; + @FXML + private Button buttonCreateNewGroupe; + + private ObservableList<GroupListItem> groups = FXCollections.observableArrayList(); + private GroupRepositoryVM groupRepositoryVM; + private KiwiViewModelHandler viewModelHandler; + private LightingMoodMainPanelController lightingMoodController; + private CompositionMainPanelController comositionController; + + public void init(KiwiViewModelHandler viewModelHandler, LightingMoodMainPanelController lightingMoodController, CompositionMainPanelController comositionController) { + this.viewModelHandler = viewModelHandler; + this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); + this.lightingMoodController = lightingMoodController; + this.comositionController = comositionController; + this.groupRepositoryVM.currentSelectedGroupProperty().addListener((object, oldValue, newValue) -> { + this.lightingMoodController.setLightingMoodRepository(newValue); + this.comositionController.setCompositionRepository(newValue); + }); + + + this.loadGroups(); + groupRepositoryVM.groupsListProperty().addListener((ListChangeListener.Change<? extends GroupVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(group -> { + this.groups.add(new GroupListItem(group, this.viewModelHandler)); + }); + + change.getRemoved().forEach(group -> { + int groupListIndex = -1; + for(int i = 0; i < this.groups.size(); i++) { + if(this.groups.get(i).getGroupName().equals(group.getGroupName())) { + groupListIndex = i; + break; + } + } + if(groupListIndex != -1) { + this.groups.remove(groupListIndex); + } + }); + } + }); + + this.groupsList.setItems(this.groups); + this.groupsList.setCellFactory(param -> new GroupListCell()); + this.groupsList.getItems().get(0).selectedGroup(); + + this.lightingMoodController.setLightingMoodRepository(this.groupRepositoryVM.getGroupVM(this.groupsList.getItems().get(0).getGroupName())); + this.comositionController.setCompositionRepository(this.groupRepositoryVM.getGroupVM(this.groupsList.getItems().get(0).getGroupName())); + } + + public void loadGroups() { + this.groupRepositoryVM.groupsListProperty().forEach(group -> { + GroupListItem groupListItem = new GroupListItem(group, this.viewModelHandler); + this.groups.add(groupListItem); + }); + } + + // Event Listener on Button[#buttonCreateNewGroupe].onAction + @FXML + public void createGroup(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../../group/createPanel/CreateGroup.fxml")); + Parent createGroupPanel = loader.load(); + CreateGroupController createGroupController = loader.getController(); + Scene scene = new Scene(createGroupPanel); + Stage groupDialog = new Stage(); + createGroupController.init(groupDialog, viewModelHandler); + groupDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + groupDialog.setScene(scene); + groupDialog.setTitle("Gruppe hinzuf�gen"); + groupDialog.showAndWait(); + } + +} diff --git a/src/lightControlSoftware/src/view/lightController/mainPanel/LightControllerMainPanel.fxml b/src/lightControlSoftware/src/view/lightController/mainPanel/LightControllerMainPanel.fxml new file mode 100644 index 0000000000000000000000000000000000000000..643b25ced7658f632b10c94aa301bc9e1c09baec --- /dev/null +++ b/src/lightControlSoftware/src/view/lightController/mainPanel/LightControllerMainPanel.fxml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import view.elements.ThreeStageSwitchButton?> +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> + +<AnchorPane prefHeight="60.0" prefWidth="300.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.lightController.mainPanel.LightControllerMainPanelController"> + <children> + <AnchorPane prefHeight="60.0" prefWidth="254.0" styleClass="section" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="7.0"> + <children> + <VBox alignment="CENTER_RIGHT" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="0.0"> + <children> + <ThreeStageSwitchButton fx:id="connectSwitch" maxHeight="20.0" maxWidth="45.0" minHeight="20.0" minWidth="45.0" prefHeight="20.0" prefWidth="45.0" /> + </children> + </VBox> + <VBox alignment="CENTER_RIGHT" layoutX="10.0" layoutY="10.0" styleClass="lable-box" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="0.0"> + <children> + <Label fx:id="labelInterfaceConnection" text="Nicht verbunden"> + <padding> + <Insets left="5.0" right="5.0" /> + </padding> + </Label> + </children> + </VBox> + </children> + </AnchorPane> + <Label styleClass="section-headline" text="Interface" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> +</AnchorPane> diff --git a/src/lightControlSoftware/src/view/lightController/mainPanel/LightControllerMainPanelController.java b/src/lightControlSoftware/src/view/lightController/mainPanel/LightControllerMainPanelController.java new file mode 100644 index 0000000000000000000000000000000000000000..1fe3cdff8243553e8916d96bbbd61b4e26c67ed0 --- /dev/null +++ b/src/lightControlSoftware/src/view/lightController/mainPanel/LightControllerMainPanelController.java @@ -0,0 +1,64 @@ +package view.lightController.mainPanel; + +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import view.elements.ThreeStageButtonCallBack; +import view.elements.ThreeStageSwitchButton; +import viewModel.lightController.ArtNetControlleVM; + +public class LightControllerMainPanelController implements ThreeStageButtonCallBack { + @FXML + private Label labelInterfaceConnection; + + @FXML + private ThreeStageSwitchButton connectSwitch; + + private ArtNetControlleVM artNetControlleVM; + + public void init(ArtNetControlleVM artNetControlleVM) { + this.artNetControlleVM = artNetControlleVM; + this.connectSwitch.setCallback(this); + this.artNetControlleVM.getArtNetNodeRepositoryVM().connectStateProperty().bindBidirectional(this.connectSwitch.buttonStateProperty()); + this.connectSwitch.buttonStateProperty().addListener((object, oldValue, newValue) -> { + switch(newValue) { + case ON: + Platform.runLater(() -> { + this.labelInterfaceConnection.setText("Verbunden"); + }); + break; + case OFF: + Platform.runLater(() -> { + this.labelInterfaceConnection.setText("Nicht verbunden"); + }); + break; + default: + break; + } + }); + } + + @Override + public void callClicked() { + switch(this.connectSwitch.buttonStateProperty().get()) { + case OFF: + if(this.labelInterfaceConnection.getText().equals("Verbindung wird hergestellt...")) { + this.labelInterfaceConnection.setText("Verbindung wird beendet"); + this.artNetControlleVM.disconnectFromNodes(); + } else { + this.labelInterfaceConnection.setText("Verbindung wird hergestellt..."); + this.artNetControlleVM.connectToNodes(); + } + break; + case MID: + this.labelInterfaceConnection.setText("Verbindung wird beendet"); + this.artNetControlleVM.disconnectFromNodes(); + break; + case ON: + this.labelInterfaceConnection.setText("Verbindung wird beendet"); + this.artNetControlleVM.disconnectFromNodes(); + break; + } + + } +} diff --git a/src/lightControlSoftware/src/view/lightingMood/LightingMoodListItem.java b/src/lightControlSoftware/src/view/lightingMood/LightingMoodListItem.java new file mode 100644 index 0000000000000000000000000000000000000000..f9282137445206d75fc729d528017196c2c152cf --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/LightingMoodListItem.java @@ -0,0 +1,224 @@ +package view.lightingMood; + +import java.io.IOException; +import java.util.Optional; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.fxml.FXMLLoader; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import view.elements.ThreeStageSwitchButton; +import view.lightingMood.editDeletePanel.EditDeleteLightingMoodController; +import viewModel.KiwiViewModelHandler; +import viewModel.group.GroupVM; +import viewModel.group.GroupVM.State; +import viewModel.lightingMood.LightingMoodVM; + +public class LightingMoodListItem extends AnchorPane{ + + private LightingMoodVM lightingMoodVM; + private String lightingMoodName; + private BooleanProperty selected; + private GroupVM groupVM; + + public LightingMoodListItem(LightingMoodVM lightingMoodVM, GroupVM groupVM, KiwiViewModelHandler viewModelHandler) { + this.lightingMoodVM = lightingMoodVM; + this.groupVM = groupVM; + this.lightingMoodName = lightingMoodVM.getLightingMoodName(); + selected = new SimpleBooleanProperty(false); + + setMaxHeight(80.0); + setMinHeight(80.0); + setPrefHeight(80.0); + setMaxWidth(200.0); + setMinWidth(200.0); + setPrefWidth(200.0); + FlowPane.setMargin(this, new Insets(5.0, 5.0, 5.0, 5.0)); + + VBox vBox = new VBox(); + vBox.setAlignment(Pos.CENTER_LEFT); + vBox.setLayoutX(7.0); + vBox.setLayoutY(2.0); + vBox.setMaxWidth(100.0); + AnchorPane.setBottomAnchor(vBox, 1.0); + AnchorPane.setLeftAnchor(vBox, 5.0); + AnchorPane.setRightAnchor(vBox, 5.0); + AnchorPane.setTopAnchor(vBox, 1.0); + + Label lableLightingMoodName = new Label(lightingMoodName); + lableLightingMoodName.setAlignment(Pos.TOP_LEFT); + lableLightingMoodName.setMaxHeight(34.0); + lableLightingMoodName.setWrapText(true); + lableLightingMoodName.textProperty().bind(this.lightingMoodVM.LightingMoodNameProperty()); + VBox.setVgrow(lableLightingMoodName, Priority.ALWAYS); + VBox.setMargin(lableLightingMoodName, new Insets(5.0, 0.0, 0.0, 0.0)); + + AnchorPane buttonArea = new AnchorPane(); + + VBox vBoxSwitchButton = new VBox(); + vBoxSwitchButton.setAlignment(Pos.CENTER_LEFT); + vBoxSwitchButton.setLayoutX(-1.0); + vBoxSwitchButton.setLayoutY(-1.0); + AnchorPane.setBottomAnchor(vBoxSwitchButton, 0.0); + AnchorPane.setLeftAnchor(vBoxSwitchButton, 5.0); + AnchorPane.setTopAnchor(vBoxSwitchButton, 0.0); + + ThreeStageSwitchButton switchButton = new ThreeStageSwitchButton(); + switchButton.setMaxHeight(20.0); + switchButton.setMinHeight(20.0); + switchButton.setPrefHeight(20.0); + switchButton.setMaxWidth(45.0); + switchButton.setMinWidth(45.0); + switchButton.setPrefWidth(45.0); + + if(this.lightingMoodVM.LightingMoodIsActiveProperty().get()) { + switchButton.buttonStateProperty().set(State.ON); + } + + this.lightingMoodVM.LightingMoodIsActiveProperty().addListener((object, oldValue, newValue) -> { + if(newValue) { + if(switchButton.buttonStateProperty().get() != State.ON) { + //switchButton.buttonStateProperty().set(State.ON); + } + } else { + if(switchButton.buttonStateProperty().get() != State.OFF) { + switchButton.buttonStateProperty().set(State.OFF); + } + } + }); + + + switchButton.buttonStateProperty().addListener((object, oldValue, newValue) -> { + switch(newValue) { + case ON: + this.groupVM.activateLightingMood(this.lightingMoodVM); + break; + case OFF: + this.groupVM.deactivateLightingMood(this.lightingMoodVM); + break; + default: + break; + } + }); + + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_RIGHT); + AnchorPane.setBottomAnchor(hBox, 0.0); + AnchorPane.setRightAnchor(hBox, 5.0); + AnchorPane.setTopAnchor(hBox, 0.0); + + Image icon1 = new Image("images/Edit.png"); + ImageView imageView1 = new ImageView(); + imageView1.setImage(icon1); + imageView1.setFitHeight(25.0); + imageView1.setFitWidth(25.0); + imageView1.setPickOnBounds(true); + imageView1.setPreserveRatio(true); + + + Button buttonEditGroup = new Button(); + buttonEditGroup.setMnemonicParsing(false); + buttonEditGroup.setStyle("-fx-background-color: none"); + buttonEditGroup.setOnAction(event -> { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("./editDeletePanel/EditDeleteLightingMood.fxml")); + Parent editDeleteLightingMoodPanel; + editDeleteLightingMoodPanel = loader.load(); + EditDeleteLightingMoodController editDeleteLightingMoodController = loader.getController(); + Scene scene = new Scene(editDeleteLightingMoodPanel); + Stage lightingMoodDialog = new Stage(); + editDeleteLightingMoodController.init(lightingMoodDialog, viewModelHandler); + editDeleteLightingMoodController.setGroup(this.groupVM.getGroupName()); + editDeleteLightingMoodController.setLightingMood(this.lightingMoodName); + lightingMoodDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + lightingMoodDialog.setScene(scene); + lightingMoodDialog.setTitle("Lichtstimmung bearbeiten/l�schen"); + lightingMoodDialog.showAndWait(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + buttonEditGroup.setGraphic(imageView1); + + Image icon2 = new Image("images/Delete.png"); + ImageView imageView2 = new ImageView(); + imageView2.setImage(icon2); + imageView2.setFitHeight(25.0); + imageView2.setFitWidth(25.0); + imageView2.setPickOnBounds(true); + imageView2.setPreserveRatio(true); + + + Button buttonDeleteGroup = new Button(); + buttonDeleteGroup.setMnemonicParsing(false); + buttonDeleteGroup.setStyle("-fx-background-color: none"); + buttonDeleteGroup.setOnAction(event -> { + Alert alert = new Alert(AlertType.CONFIRMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Lichtstimmung l�schen"); + alert.setHeaderText(String.format("Sind Sie sicher, dass Sie die Lichtstimmung %s l�schen m�chten", this.getLightingMoodName())); + ButtonType buttonDelete = new ButtonType("Lichstimmung l�schen"); + ButtonType buttonCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + alert.getButtonTypes().setAll(buttonDelete, buttonCancel); + Optional<ButtonType> result = alert.showAndWait(); + if (result.orElseThrow() == buttonDelete) { + this.groupVM.removeLightingMood(this.lightingMoodVM); + } + }); + buttonDeleteGroup.setGraphic(imageView2); + + + vBoxSwitchButton.getChildren().add(switchButton); + hBox.getChildren().addAll(buttonEditGroup, buttonDeleteGroup); + buttonArea.getChildren().addAll(vBoxSwitchButton, hBox); + vBox.getChildren().addAll(lableLightingMoodName, buttonArea); + getChildren().addAll(vBox); + getStyleClass().addAll("list-item", "item-diselected"); + + this.selected.bind(this.lightingMoodVM.LightingMoodIsSelectedProperty()); + + this.selected.addListener((object, oldValue, newValue) -> { + if(newValue) { + this.getStyleClass().add("item-selected"); + this.getStyleClass().remove("item-diselected"); + } else { + this.getStyleClass().add("item-diselected"); + this.getStyleClass().remove("item-selected"); + } + }); + + this.setOnMouseClicked(event -> { + this.lightingMoodVM.setLightingMoodIsSelected(true); + }); + } + + public boolean isSelected() { + return selected.get(); + } + + public BooleanProperty selectedProperty() { + return this.selected; + } + + public String getLightingMoodName() { + return this.lightingMoodName; + } +} diff --git a/src/lightControlSoftware/src/view/lightingMood/createPanel/CreateLightingMood.fxml b/src/lightControlSoftware/src/view/lightingMood/createPanel/CreateLightingMood.fxml new file mode 100644 index 0000000000000000000000000000000000000000..b092a8344c2a1fcd793ad3bf38eded3e58eb602e --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/createPanel/CreateLightingMood.fxml @@ -0,0 +1,194 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ColorPicker?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.Separator?> +<?import javafx.scene.control.Slider?> +<?import javafx.scene.control.Spinner?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="350.0" minWidth="500.0" prefHeight="350.0" prefWidth="500.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.lightingMood.createPanel.CreateLightingMoodController"> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"> + <children> + <BorderPane HBox.hgrow="ALWAYS"> + <HBox.margin> + <Insets /> + </HBox.margin> + <center> + <Slider fx:id="sliderMainIntensity" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" orientation="VERTICAL" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets bottom="10.0" top="5.0" /> + </BorderPane.margin> + </Slider> + </center> + <top> + <Label text="Dimmer" BorderPane.alignment="TOP_CENTER"> + <BorderPane.margin> + <Insets top="5.0" /> + </BorderPane.margin> + </Label> + </top> + <bottom> + <Spinner fx:id="spinnerMainIntensity" editable="true" maxWidth="65.0" BorderPane.alignment="BOTTOM_CENTER" /> + </bottom> + </BorderPane> + <BorderPane HBox.hgrow="ALWAYS"> + <center> + <Slider fx:id="sliderStrope" majorTickUnit="50.0" max="255.0" minorTickCount="5" orientation="VERTICAL" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets bottom="10.0" top="5.0" /> + </BorderPane.margin> + </Slider> + </center> + <top> + <Label text="Strobe" BorderPane.alignment="TOP_CENTER"> + <BorderPane.margin> + <Insets top="5.0" /> + </BorderPane.margin> + </Label> + </top> + <bottom> + <Spinner fx:id="spinnerStrope" editable="true" maxWidth="65.0" BorderPane.alignment="BOTTOM_CENTER" /> + </bottom> + <HBox.margin> + <Insets left="15.0" /> + </HBox.margin> + </BorderPane> + <BorderPane HBox.hgrow="ALWAYS"> + <top> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Label text="Farbe" /> + <ColorPicker fx:id="colorPicker"> + <HBox.margin> + <Insets left="10.0" /> + </HBox.margin> + </ColorPicker> + </children> + <opaqueInsets> + <Insets /> + </opaqueInsets> + <BorderPane.margin> + <Insets left="5.0" /> + </BorderPane.margin> + </HBox> + </top> + <center> + <VBox BorderPane.alignment="CENTER"> + <children> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderRed" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="30.0" text="Rot" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerRed" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderGreen" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="30.0" text="Grün" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerGreen" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderBlue" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="30.0" text="Blau" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerBlue" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + </children> + <BorderPane.margin> + <Insets top="10.0" /> + </BorderPane.margin> + </VBox> + </center> + <HBox.margin> + <Insets left="20.0" /> + </HBox.margin> + </BorderPane> + </children> + </HBox> + </children> + </AnchorPane> + </center> + <top> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets bottom="5.0" left="10.0" right="10.0" top="10.0" /> + </VBox.margin> + <children> + <HBox alignment="CENTER_LEFT" HBox.hgrow="ALWAYS"> + <children> + <Label minWidth="65.0" text="Gruppe" /> + <ComboBox fx:id="comboBoxGroup" minWidth="150.0" HBox.hgrow="ALWAYS" /> + </children> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin> + </HBox> + <Separator orientation="VERTICAL" HBox.hgrow="ALWAYS" /> + <HBox alignment="CENTER_LEFT" HBox.hgrow="ALWAYS"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*" /> + <TextField fx:id="textfieldName" HBox.hgrow="ALWAYS" /> + </children> + </HBox> + </children> + </HBox> + </children> + </VBox> + </top> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonCreateLightingMood" mnemonicParsing="false" onAction="#createLightingMood" text="Lichtstimmung hinzufügen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/lightingMood/createPanel/CreateLightingMoodController.java b/src/lightControlSoftware/src/view/lightingMood/createPanel/CreateLightingMoodController.java new file mode 100644 index 0000000000000000000000000000000000000000..f9a4db6685d52cae068ead5ed726630877d14d99 --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/createPanel/CreateLightingMoodController.java @@ -0,0 +1,211 @@ +package view.lightingMood.createPanel; + +import javafx.fxml.FXML; +import javafx.scene.control.ColorPicker; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.image.Image; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.scene.control.Slider; +import javafx.scene.control.ComboBox; +import javafx.scene.control.Spinner; +import javafx.scene.control.SpinnerValueFactory; +import javafx.scene.layout.BorderPane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import model.lightingScene.lightingMood.LightingMood; +import viewModel.group.GroupRepositoryVM; +import viewModel.lightingMood.LightingMoodVM; + +public class CreateLightingMoodController { + @FXML + private BorderPane root; + @FXML + private Slider sliderMainIntensity; + @FXML + private Spinner<Integer> spinnerMainIntensity; + @FXML + private Slider sliderStrope; + @FXML + private Spinner<Integer> spinnerStrope; + @FXML + private ColorPicker colorPicker; + @FXML + private Slider sliderRed; + @FXML + private Spinner<Integer> spinnerRed; + @FXML + private Slider sliderGreen; + @FXML + private Spinner<Integer> spinnerGreen; + @FXML + private Slider sliderBlue; + @FXML + private Spinner<Integer> spinnerBlue; + @FXML + private ComboBox<String> comboBoxGroup; + @FXML + private TextField textfieldName; + @FXML + private Button buttonCreateLightingMood; + @FXML + private Button buttonCancel; + + private GroupRepositoryVM groupRepositoryVM; + private ObservableList<String> groupNames = FXCollections.observableArrayList(); + private Stage stage; + + + public void init(Stage stage, GroupRepositoryVM groupRepositoryVM) { + this.stage = stage; + this.groupRepositoryVM = groupRepositoryVM; + this.spinnerMainIntensity.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.spinnerStrope.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerRed.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.spinnerGreen.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.spinnerBlue.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.addListener(); + this.loadGroups(); + } + + public void setGroup(String groupName) { + this.comboBoxGroup.setValue(groupName); + } + + // Event Listener on Button[#buttonCreateLightingMood].onAction + @FXML + public void createLightingMood(ActionEvent event) { + if(this.isDataValid()) { + + try { + LightingMoodVM lightingMoodVM = new LightingMoodVM(new LightingMood(this.textfieldName.getText())); + lightingMoodVM.setLightingMoodMainIntensity(this.sliderMainIntensity.valueProperty().intValue()); + lightingMoodVM.setLightingMoodStrope(this.sliderStrope.valueProperty().intValue()); + lightingMoodVM.setLightingMoodRed(this.sliderRed.valueProperty().intValue()); + lightingMoodVM.setLightingMoodGreen(this.sliderGreen.valueProperty().intValue()); + lightingMoodVM.setLightingMoodBlue(this.sliderBlue.valueProperty().intValue()); + + this.groupRepositoryVM + .getGroupVM(this.comboBoxGroup.getValue()) + .addLightingMood(lightingMoodVM); + this.stage.close(); + } catch (IllegalArgumentException e) { + Alert alert = new Alert(AlertType.ERROR); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Fehler"); + alert.setHeaderText("Fehler beim Erstellen einer Lichtstimmung."); + alert.setContentText(e.getMessage()); + alert.showAndWait(); + } + } + } + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textfieldName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + private void addListener() { + this.addSpinnerListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSpinnerListener(this.spinnerStrope, this.sliderStrope); + this.addSpinnerListener(this.spinnerRed, this.sliderRed); + this.addSpinnerListener(this.spinnerGreen, this.sliderGreen); + this.addSpinnerListener(this.spinnerBlue, this.sliderBlue); + + this.addSliderListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSliderListener(this.spinnerStrope, this.sliderStrope); + this.addSliderListener(this.spinnerRed, this.sliderRed); + this.addSliderListener(this.spinnerGreen, this.sliderGreen); + this.addSliderListener(this.spinnerBlue, this.sliderBlue); + + this.colorPicker.valueProperty().addListener((onject, oldValue, newValue) -> { + this.sliderRed.setValue(newValue.getRed()*255); + this.sliderGreen.setValue(newValue.getGreen()*255); + this.sliderBlue.setValue(newValue.getBlue()*255); + }); + + this.sliderRed.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + (double)newValue/255, + this.sliderGreen.getValue()/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderGreen.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + (double)newValue/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderBlue.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + this.sliderGreen.getValue()/255, + (double)newValue/255, 1 + )); + }); + } + + private void addSpinnerListener (Spinner<Integer> spinner, Slider slider) { + spinner.getValueFactory().valueProperty().addListener((object, oldValue, newValue) -> { + slider.valueProperty().set(newValue.doubleValue()); + }); + } + + private void addSliderListener (Spinner<Integer> spinner, Slider slider) { + slider.valueProperty().addListener((object, oldValue, newValue) -> { + spinner.getValueFactory().setValue(newValue.intValue()); + }); + } + + private void loadGroups() { + this.groupNames.clear(); + this.groupRepositoryVM.groupsListProperty().forEach(groupVM -> { + this.groupNames.add(groupVM.getGroupName()); + }); + this.comboBoxGroup.setItems(this.groupNames); + this.comboBoxGroup.setValue(this.groupNames.get(0)); + } +} diff --git a/src/lightControlSoftware/src/view/lightingMood/editDeletePanel/EditDeleteLightingMood.fxml b/src/lightControlSoftware/src/view/lightingMood/editDeletePanel/EditDeleteLightingMood.fxml new file mode 100644 index 0000000000000000000000000000000000000000..9ead1aae6e38822a606eedd4c8e2ba9f0d61df8a --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/editDeletePanel/EditDeleteLightingMood.fxml @@ -0,0 +1,227 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ColorPicker?> +<?import javafx.scene.control.ComboBox?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.Separator?> +<?import javafx.scene.control.Slider?> +<?import javafx.scene.control.Spinner?> +<?import javafx.scene.control.TextField?> +<?import javafx.scene.image.Image?> +<?import javafx.scene.image.ImageView?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> + +<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="350.0" minWidth="550.0" prefHeight="350.0" prefWidth="550.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.lightingMood.editDeletePanel.EditDeleteLightingMoodController"> + <center> + <AnchorPane BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="5.0"> + <children> + <BorderPane HBox.hgrow="ALWAYS"> + <HBox.margin> + <Insets /> + </HBox.margin> + <center> + <Slider fx:id="sliderMainIntensity" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" orientation="VERTICAL" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets bottom="10.0" top="5.0" /> + </BorderPane.margin> + </Slider> + </center> + <top> + <Label text="Dimmer" BorderPane.alignment="TOP_CENTER"> + <BorderPane.margin> + <Insets top="5.0" /> + </BorderPane.margin> + </Label> + </top> + <bottom> + <Spinner fx:id="spinnerMainIntensity" editable="true" maxWidth="65.0" BorderPane.alignment="BOTTOM_CENTER" /> + </bottom> + </BorderPane> + <BorderPane HBox.hgrow="ALWAYS"> + <center> + <Slider fx:id="sliderStrope" majorTickUnit="50.0" max="255.0" minorTickCount="5" orientation="VERTICAL" showTickLabels="true" showTickMarks="true" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets bottom="10.0" top="5.0" /> + </BorderPane.margin> + </Slider> + </center> + <top> + <Label text="Strobe" BorderPane.alignment="TOP_CENTER"> + <BorderPane.margin> + <Insets top="5.0" /> + </BorderPane.margin> + </Label> + </top> + <bottom> + <Spinner fx:id="spinnerStrope" editable="true" maxWidth="65.0" BorderPane.alignment="BOTTOM_CENTER" /> + </bottom> + <HBox.margin> + <Insets left="15.0" /> + </HBox.margin> + </BorderPane> + <BorderPane HBox.hgrow="ALWAYS"> + <top> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Label text="Farbe" /> + <ColorPicker fx:id="colorPicker"> + <HBox.margin> + <Insets left="10.0" /> + </HBox.margin> + </ColorPicker> + </children> + <opaqueInsets> + <Insets /> + </opaqueInsets> + <BorderPane.margin> + <Insets left="5.0" /> + </BorderPane.margin> + </HBox> + </top> + <center> + <VBox BorderPane.alignment="CENTER"> + <children> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderRed" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="30.0" text="Rot" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerRed" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderGreen" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="30.0" text="Grün" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerGreen" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + <BorderPane VBox.vgrow="ALWAYS"> + <center> + <Slider fx:id="sliderBlue" blockIncrement="5.0" majorTickUnit="50.0" max="255.0" minorTickCount="5" showTickLabels="true" showTickMarks="true" value="255.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets left="10.0" right="10.0" /> + </BorderPane.margin> + </Slider> + </center> + <left> + <Label minWidth="30.0" text="Blau" BorderPane.alignment="CENTER" /> + </left> + <right> + <Spinner fx:id="spinnerBlue" editable="true" maxWidth="65.0" BorderPane.alignment="CENTER" /> + </right> + </BorderPane> + </children> + <BorderPane.margin> + <Insets top="10.0" /> + </BorderPane.margin> + </VBox> + </center> + <HBox.margin> + <Insets left="20.0" /> + </HBox.margin> + </BorderPane> + </children> + </HBox> + </children> + </AnchorPane> + </center> + <top> + <VBox BorderPane.alignment="CENTER"> + <children> + <HBox alignment="CENTER_LEFT" VBox.vgrow="ALWAYS"> + <children> + <HBox alignment="CENTER_LEFT" HBox.hgrow="ALWAYS"> + <children> + <Label minWidth="45.0" text="Gruppe" HBox.hgrow="NEVER" /> + <ComboBox fx:id="comboBoxGroup" minWidth="150.0" onAction="#selectGroup" HBox.hgrow="ALWAYS" /> + </children> + <HBox.margin> + <Insets right="10.0" /> + </HBox.margin> + </HBox> + <Separator orientation="VERTICAL" HBox.hgrow="ALWAYS" /> + <HBox alignment="CENTER_LEFT" HBox.hgrow="ALWAYS"> + <children> + <Label minWidth="85.0" text="Lichtstimmung" HBox.hgrow="NEVER" /> + <ComboBox fx:id="comboBoxLightingMood" minWidth="150.0" onAction="#selectLightingMood" HBox.hgrow="ALWAYS" /> + </children> + <HBox.margin> + <Insets left="20.0" right="5.0" /> + </HBox.margin> + </HBox> + <Button fx:id="buttonDelete" mnemonicParsing="false" onAction="#deleteLightingMood" style="-fx-background-color: none;" HBox.hgrow="ALWAYS"> + <graphic> + <ImageView fitHeight="20.0" fitWidth="20.0" pickOnBounds="true" preserveRatio="true"> + <image> + <Image url="@../../../../ressourcen/images/Delete.png" /> + </image> + </ImageView> + </graphic> + </Button> + </children> + <VBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </VBox.margin> + </HBox> + <HBox alignment="CENTER_LEFT" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets bottom="5.0" left="10.0" right="10.0" top="5.0" /> + </VBox.margin> + <children> + <HBox alignment="CENTER_LEFT"> + <children> + <Label maxWidth="75.0" minWidth="75.0" prefWidth="75.0" text="Bezeichnung*"> + <HBox.margin> + <Insets right="5.0" /> + </HBox.margin></Label> + <TextField fx:id="textfieldName" /> + </children> + <HBox.margin> + <Insets right="10.0" /> + </HBox.margin> + </HBox> + </children> + </HBox> + </children> + </VBox> + </top> + <bottom> + <HBox alignment="CENTER" BorderPane.alignment="CENTER"> + <children> + <Button fx:id="buttonSave" mnemonicParsing="false" onAction="#saveLightingMood" text="Speichern"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + <Button fx:id="buttonCancel" mnemonicParsing="false" onAction="#cancel" text="Abbrechen"> + <HBox.margin> + <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> + </HBox.margin> + </Button> + </children> + </HBox> + </bottom> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/lightingMood/editDeletePanel/EditDeleteLightingMoodController.java b/src/lightControlSoftware/src/view/lightingMood/editDeletePanel/EditDeleteLightingMoodController.java new file mode 100644 index 0000000000000000000000000000000000000000..81a0cddc30d376a672249745ccb18837e46d7cd8 --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/editDeletePanel/EditDeleteLightingMoodController.java @@ -0,0 +1,299 @@ +package view.lightingMood.editDeletePanel; + +import javafx.fxml.FXML; + +import javafx.scene.control.ColorPicker; +import javafx.scene.control.Alert; +import javafx.scene.control.Button; +import javafx.scene.control.ButtonType; +import javafx.scene.control.TextField; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.ButtonBar.ButtonData; +import javafx.scene.image.Image; + +import java.util.Optional; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; + +import javafx.scene.control.Slider; + +import javafx.scene.control.ComboBox; + +import javafx.scene.control.Spinner; +import javafx.scene.control.SpinnerValueFactory; +import javafx.scene.layout.BorderPane; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import model.lightingScene.lightingMood.LightingMood; +import viewModel.KiwiViewModelHandler; +import viewModel.group.GroupRepositoryVM; +import viewModel.group.GroupVM; +import viewModel.lightingMood.LightingMoodRepositoryVM; +import viewModel.lightingMood.LightingMoodVM; + +public class EditDeleteLightingMoodController { + @FXML + private BorderPane root; + @FXML + private Slider sliderMainIntensity; + @FXML + private Spinner<Integer> spinnerMainIntensity; + @FXML + private Slider sliderStrope; + @FXML + private Spinner<Integer> spinnerStrope; + @FXML + private ColorPicker colorPicker; + @FXML + private Slider sliderRed; + @FXML + private Spinner<Integer> spinnerRed; + @FXML + private Slider sliderGreen; + @FXML + private Spinner<Integer> spinnerGreen; + @FXML + private Slider sliderBlue; + @FXML + private Spinner<Integer> spinnerBlue; + @FXML + private ComboBox<String> comboBoxLightingMood; + @FXML + private ComboBox<String> comboBoxGroup; + @FXML + private TextField textfieldName; + @FXML + private Button buttonSave; + @FXML + private Button buttonCancel; + @FXML + private Button buttonDelete; + + private Stage stage; + private ObservableList<String> groupNames = FXCollections.observableArrayList(); + private ObservableList<String> lightingMoodNames = FXCollections.observableArrayList(); + private GroupRepositoryVM groupRepositoryVM; + private LightingMoodRepositoryVM lightingMoodRepositoryVM; + private GroupVM groupVM; + private LightingMoodVM lightingMoodVM; + + public void init(Stage stage, KiwiViewModelHandler viewModelHandler) { + this.stage = stage; + this.groupRepositoryVM = viewModelHandler.getGroupRepositoryVM(); + this.spinnerMainIntensity.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.spinnerStrope.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 0)); + this.spinnerRed.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.spinnerGreen.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.spinnerBlue.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 255, 255)); + this.addListener(); + this.loadGroups(); + } + + // Event Listener on ComboBox[#comboBoxGroup].onAction + @FXML + public void selectGroup(ActionEvent event) { + if(!(this.comboBoxGroup.getValue() == null)) { + this.groupVM = groupRepositoryVM.getGroupVM(this.comboBoxGroup.getValue()); + this.loadLightingMoods(); + } + } + + // Event Listener on ComboBox[#comboBoxLightingMood].onAction + @FXML + public void selectLightingMood(ActionEvent event) { + if(!(this.comboBoxLightingMood.getValue() == null)) { + this.lightingMoodVM = lightingMoodRepositoryVM.getLightingMood(this.comboBoxLightingMood.getValue()); + this.updateLightingMood(); + } + } + + // Event Listener on Button[#buttonDelete].onAction + public void deleteLightingMood(ActionEvent event) { + Alert alert = new Alert(AlertType.CONFIRMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Lichtstimmung l�schen"); + alert.setHeaderText(String.format("Sind Sie sicher, dass Sie die Lichtstimmung %s l�schen m�chten", this.lightingMoodVM.getLightingMoodName())); + ButtonType buttonDelete = new ButtonType("Lichtstimmung l�schen"); + ButtonType buttonCancel = new ButtonType("Abbrechen", ButtonData.CANCEL_CLOSE); + alert.getButtonTypes().setAll(buttonDelete, buttonCancel); + Optional<ButtonType> result = alert.showAndWait(); + if (result.orElseThrow() == buttonDelete) { + this.lightingMoodRepositoryVM.removeLightingMood(lightingMoodVM); + this.loadLightingMoods(); + } + } + + // Event Listener on Button[#buttonSave].onAction + @FXML + public void saveLightingMood(ActionEvent event) { + if(isDataValid()) { + this.lightingMoodVM.setLightingMoodName(this.textfieldName.getText()); + this.lightingMoodVM.setLightingMoodMainIntensity(this.sliderMainIntensity.valueProperty().getValue().intValue()); + this.lightingMoodVM.setLightingMoodStrope(this.sliderStrope.valueProperty().getValue().intValue()); + this.lightingMoodVM.setLightingMoodRed(this.sliderRed.valueProperty().getValue().intValue()); + this.lightingMoodVM.setLightingMoodGreen(this.sliderGreen.valueProperty().getValue().intValue()); + this.lightingMoodVM.setLightingMoodBlue(this.sliderBlue.valueProperty().getValue().intValue()); + this.stage.close(); + } + } + + // Event Listener on Button[#buttonCancel].onAction + @FXML + public void cancel(ActionEvent event) { + this.stage.close(); + } + + private void addListener() { + this.addSpinnerListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSpinnerListener(this.spinnerStrope, this.sliderStrope); + this.addSpinnerListener(this.spinnerRed, this.sliderRed); + this.addSpinnerListener(this.spinnerGreen, this.sliderGreen); + this.addSpinnerListener(this.spinnerBlue, this.sliderBlue); + + this.addSliderListener(this.spinnerMainIntensity, this.sliderMainIntensity); + this.addSliderListener(this.spinnerStrope, this.sliderStrope); + this.addSliderListener(this.spinnerRed, this.sliderRed); + this.addSliderListener(this.spinnerGreen, this.sliderGreen); + this.addSliderListener(this.spinnerBlue, this.sliderBlue); + + this.colorPicker.valueProperty().addListener((onject, oldValue, newValue) -> { + this.sliderRed.setValue(newValue.getRed()*255); + this.sliderGreen.setValue(newValue.getGreen()*255); + this.sliderBlue.setValue(newValue.getBlue()*255); + }); + + this.sliderRed.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + (double)newValue/255, + this.sliderGreen.getValue()/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderGreen.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + (double)newValue/255, + this.sliderBlue.getValue()/255, 1 + )); + }); + + this.sliderBlue.valueProperty().addListener((object, oldValue, newValue) -> { + this.colorPicker + .valueProperty() + .setValue( + new Color( + this.sliderRed.getValue()/255, + this.sliderGreen.getValue()/255, + (double)newValue/255, 1 + )); + }); + } + + private void addSpinnerListener (Spinner<Integer> spinner, Slider slider) { + spinner.getValueFactory().valueProperty().addListener((object, oldValue, newValue) -> { + slider.valueProperty().set(newValue.doubleValue()); + }); + } + + private void addSliderListener (Spinner<Integer> spinner, Slider slider) { + slider.valueProperty().addListener((object, oldValue, newValue) -> { + spinner.getValueFactory().setValue(newValue.intValue()); + }); + } + + private void loadGroups() { + this.groupNames.clear(); + this.groupRepositoryVM.groupsListProperty().forEach(groupVM -> { + this.groupNames.add(groupVM.getGroupName()); + }); + this.groupVM = groupRepositoryVM.getGroupVM(this.groupNames.get(0)); + this.comboBoxGroup.setItems(this.groupNames); + this.comboBoxGroup.setValue(this.groupNames.get(0)); + this.loadLightingMoods(); + } + + private void loadLightingMoods() { + this.lightingMoodNames.clear(); + this.lightingMoodRepositoryVM = groupVM.getLightingMoodRepositoryVM(); + this.lightingMoodRepositoryVM.lightingMoodListProperty().forEach(lightingMoodVM -> { + this.lightingMoodNames.add(lightingMoodVM.getLightingMoodName()); + }); + this.comboBoxLightingMood.setItems(this.lightingMoodNames); + if(lightingMoodRepositoryVM.lightingMoodListProperty().size() > 0) { + this.lightingMoodVM = lightingMoodRepositoryVM.getLightingMood(this.lightingMoodNames.get(0)); + this.comboBoxLightingMood.setValue(this.lightingMoodNames.get(0)); + } else { + this.lightingMoodVM = new LightingMoodVM(new LightingMood("Lichtstimmung")); + } + this.updateLightingMood(); + } + + public void updateLightingMood() { + this.textfieldName.setText(this.lightingMoodVM.getLightingMoodName()); + this.sliderMainIntensity.valueProperty().set(this.lightingMoodVM.getLightingMoodMainIntensity()); + this.sliderStrope.valueProperty().set(this.lightingMoodVM.getLightingMoodStrope()); + this.sliderRed.valueProperty().set(this.lightingMoodVM.getLightingMoodRed()); + this.sliderGreen.valueProperty().set(this.lightingMoodVM.getLightingMoodGreen()); + this.sliderBlue.valueProperty().set(this.lightingMoodVM.getLightingMoodBlue()); + } + + private boolean isDataValid() { + boolean isValid = false; + String headerText = ""; + String contentText = ""; + + if(this.textfieldName.getText().isEmpty()) { + headerText = "Fehlerhafter Name."; + contentText = "Das Namensfeld darf nicht leer sein."; + } else if(this.nameAllreadyExist(this.textfieldName.getText())) { + headerText = "Fehlerhafter Name."; + contentText = "Der Name ist bereits in Benutzung."; + } else { + isValid = true; + } + + if(!isValid) { + Alert alert = new Alert(AlertType.WARNING); + alert.setTitle("Warnung"); + alert.setHeaderText(headerText); + alert.setContentText(contentText); + alert.showAndWait(); + } + + return isValid; + } + + private boolean nameAllreadyExist(String name) { + boolean nameExist = false; + if(!this.lightingMoodVM.getLightingMoodName().equals(name) && + this.lightingMoodNames.stream() + .filter(lightingMoodName -> lightingMoodName.equals(name)) + .count() > 0){ + nameExist = true; + } + + return nameExist; + } + + public void setGroup(String groupName) { + this.comboBoxGroup.valueProperty().set(groupName); + this.groupVM = groupRepositoryVM.getGroupVM(this.comboBoxGroup.getValue()); + this.loadLightingMoods(); + } + + public void setLightingMood(String lightingMoodName) { + this.comboBoxLightingMood.valueProperty().set(lightingMoodName); + this.lightingMoodVM = lightingMoodRepositoryVM.getLightingMood(this.comboBoxLightingMood.getValue()); + this.updateLightingMood(); + } +} diff --git a/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanel.fxml b/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanel.fxml new file mode 100644 index 0000000000000000000000000000000000000000..6de82c3e9a075f7a0593b6aa9ec6d0f85e181f3d --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanel.fxml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.FlowPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.text.Font?> + +<AnchorPane prefHeight="350.0" prefWidth="880.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.lightingMood.mainPanel.LightingMoodMainPanelController"> + <children> + <AnchorPane layoutX="5.0" layoutY="7.0" styleClass="section" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0"> + <children> + <HBox layoutX="7.0" layoutY="12.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <BorderPane HBox.hgrow="ALWAYS"> + <center> + <ScrollPane fitToHeight="true" fitToWidth="true"> + <content> + <FlowPane fx:id="flowPaneLightingMoodList" /> + </content> + </ScrollPane> + </center> + <top> + <Button fx:id="buttonCreateNewLightingMood" mnemonicParsing="false" onAction="#createLightingMood" text="Neue Lichtstimmung erstellen" BorderPane.alignment="CENTER_LEFT"> + <BorderPane.margin> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </BorderPane.margin> + </Button> + </top> + </BorderPane> + </children> + </HBox> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </padding> + </AnchorPane> + <Label layoutX="20.0" styleClass="section-headline" text="Lichtstimmung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> +</AnchorPane> diff --git a/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanel2.fxml b/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanel2.fxml new file mode 100644 index 0000000000000000000000000000000000000000..5eead5dff7b698ee29e2f14a774230483b569eb3 --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanel2.fxml @@ -0,0 +1,111 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Button?> +<?import javafx.scene.control.ColorPicker?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.ScrollPane?> +<?import javafx.scene.control.Separator?> +<?import javafx.scene.control.Slider?> +<?import javafx.scene.control.Spinner?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.FlowPane?> +<?import javafx.scene.layout.HBox?> +<?import javafx.scene.layout.VBox?> +<?import javafx.scene.text.Font?> + +<AnchorPane prefHeight="350.0" prefWidth="880.0" stylesheets="@../../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.lightingMood.mainPanel.LightingMoodMainPanelController"> + <children> + <AnchorPane layoutX="5.0" layoutY="7.0" styleClass="section" AnchorPane.bottomAnchor="5.0" AnchorPane.leftAnchor="5.0" AnchorPane.rightAnchor="5.0" AnchorPane.topAnchor="5.0"> + <children> + <HBox layoutX="7.0" layoutY="12.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <BorderPane HBox.hgrow="ALWAYS"> + <center> + <ScrollPane fitToHeight="true" fitToWidth="true"> + <content> + <FlowPane fx:id="flowPaneLightingMoodList" /> + </content> + </ScrollPane> + </center> + <top> + <Button fx:id="buttonCreateNewLightingMood" mnemonicParsing="false" onAction="#createLightingMood" text="Neue Lichtstimmung erstellen" BorderPane.alignment="CENTER_LEFT"> + <BorderPane.margin> + <Insets bottom="5.0" left="5.0" top="5.0" /> + </BorderPane.margin> + </Button> + </top> + </BorderPane> + <Separator orientation="VERTICAL" prefHeight="200.0" /> + <VBox alignment="CENTER" HBox.hgrow="NEVER"> + <children> + <ColorPicker fx:id="colorPicker" VBox.vgrow="ALWAYS"> + <VBox.margin> + <Insets bottom="10.0" /> + </VBox.margin> + </ColorPicker> + <HBox alignment="CENTER"> + <children> + <VBox alignment="CENTER"> + <children> + <Label text="Dimmer"> + <VBox.margin> + <Insets bottom="5.0" /> + </VBox.margin> + </Label> + <Slider fx:id="faderIntensity" maxHeight="150.0" minHeight="150.0" orientation="VERTICAL" prefHeight="150.0"> + <VBox.margin> + <Insets bottom="5.0" top="5.0" /> + </VBox.margin> + </Slider> + <Spinner fx:id="spinnerIntensity" maxHeight="20.0" minHeight="20.0" prefHeight="20.0" prefWidth="60.0"> + <VBox.margin> + <Insets top="5.0" /> + </VBox.margin> + </Spinner> + </children> + <HBox.margin> + <Insets left="10.0" right="10.0" /> + </HBox.margin> + </VBox> + <VBox alignment="CENTER"> + <children> + <Label text="Strope"> + <VBox.margin> + <Insets bottom="5.0" /> + </VBox.margin> + </Label> + <Slider fx:id="faderStrope" maxHeight="150.0" minHeight="150.0" orientation="VERTICAL" prefHeight="150.0"> + <VBox.margin> + <Insets bottom="5.0" top="5.0" /> + </VBox.margin> + </Slider> + <Spinner fx:id="spinnerStrope" maxHeight="20.0" minHeight="20.0" prefHeight="20.0" prefWidth="60.0"> + <VBox.margin> + <Insets top="5.0" /> + </VBox.margin> + </Spinner> + </children> + <HBox.margin> + <Insets left="10.0" right="10.0" /> + </HBox.margin> + </VBox> + </children> + </HBox> + </children> + </VBox> + </children> + </HBox> + </children> + <padding> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </padding> + </AnchorPane> + <Label layoutX="20.0" styleClass="section-headline" text="Lichtstimmung" AnchorPane.leftAnchor="20.0" AnchorPane.topAnchor="0.0"> + <font> + <Font name="System Bold" size="12.0" /> + </font> + </Label> + </children> +</AnchorPane> diff --git a/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanelController.java b/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanelController.java new file mode 100644 index 0000000000000000000000000000000000000000..6d8f6b79aff7b70b3e27e78a4c8959d102e6b565 --- /dev/null +++ b/src/lightControlSoftware/src/view/lightingMood/mainPanel/LightingMoodMainPanelController.java @@ -0,0 +1,89 @@ +package view.lightingMood.mainPanel; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import java.io.IOException; +import javafx.collections.ListChangeListener; +import javafx.event.ActionEvent; +import javafx.scene.layout.FlowPane; +import javafx.stage.Stage; +import view.lightingMood.LightingMoodListItem; +import view.lightingMood.createPanel.CreateLightingMoodController; +import viewModel.KiwiViewModelHandler; +import viewModel.group.GroupVM; +import viewModel.lightingMood.LightingMoodRepositoryVM; +import viewModel.lightingMood.LightingMoodVM; +import javafx.scene.image.Image; + +public class LightingMoodMainPanelController { + @FXML + private FlowPane flowPaneLightingMoodList; + @FXML + private Button buttonCreateNewLightingMood; + + private KiwiViewModelHandler viewModelHandler; + private LightingMoodRepositoryVM lightingMoodRepositoryVM; + private GroupVM groupVM; + + public void init(KiwiViewModelHandler viewModelHandler) { + this.viewModelHandler = viewModelHandler; + } + + // Event Listener on Button[#buttonCreateNewLightingMood].onAction + @FXML + public void createLightingMood(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../createPanel/CreateLightingMood.fxml")); + Parent createLightingMoodPanel = loader.load(); + CreateLightingMoodController createLightingMoodController = loader.getController(); + Scene scene = new Scene(createLightingMoodPanel); + Stage lightingMoodDialog = new Stage(); + createLightingMoodController.init(lightingMoodDialog, this.viewModelHandler.getGroupRepositoryVM()); + createLightingMoodController.setGroup(this.groupVM.getGroupName()); + lightingMoodDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + lightingMoodDialog.setScene(scene); + lightingMoodDialog.setTitle("Lichtstimmung erstellen"); + lightingMoodDialog.showAndWait(); + } + + private void addLightingMoodToPane(LightingMoodVM lightingMoodVM) { + this.flowPaneLightingMoodList.getChildren().add(new LightingMoodListItem(lightingMoodVM, groupVM, this.viewModelHandler)); + } + + public void setLightingMoodRepository(GroupVM groupVM) { + this.groupVM = groupVM; + this.lightingMoodRepositoryVM = groupVM.getLightingMoodRepositoryVM(); + this.flowPaneLightingMoodList.getChildren().clear(); + this.lightingMoodRepositoryVM.lightingMoodListProperty().forEach(lightingMoodVM -> { + this.addLightingMoodToPane(lightingMoodVM); + }); + + this.lightingMoodRepositoryVM.lightingMoodListProperty().addListener((ListChangeListener.Change<? extends LightingMoodVM> change) -> { + while(change.next()) { + change.getAddedSubList().forEach(lightingMoodVM -> { + addLightingMoodToPane(lightingMoodVM); + }); + + change.getRemoved().forEach(lightingMoodVM -> { + int lightingMoodListIndex = -1; + for(int i = 0; i < this.flowPaneLightingMoodList.getChildren().size(); i++) { + if(((LightingMoodListItem)this.flowPaneLightingMoodList + .getChildren() + .get(i)) + .getLightingMoodName() + .equals(lightingMoodVM.getLightingMoodName())) { + lightingMoodListIndex = i; + break; + } + } + if(lightingMoodListIndex != -1) { + this.flowPaneLightingMoodList.getChildren().remove(lightingMoodListIndex); + } + }); + } + }); + } + +} diff --git a/src/lightControlSoftware/src/view/mainScene/MainScene.fxml b/src/lightControlSoftware/src/view/mainScene/MainScene.fxml new file mode 100644 index 0000000000000000000000000000000000000000..20712fefe4c804ae87e0500439943b32fd62277f --- /dev/null +++ b/src/lightControlSoftware/src/view/mainScene/MainScene.fxml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<?import javafx.geometry.Insets?> +<?import javafx.scene.control.Label?> +<?import javafx.scene.control.Menu?> +<?import javafx.scene.control.MenuBar?> +<?import javafx.scene.control.MenuItem?> +<?import javafx.scene.control.SeparatorMenuItem?> +<?import javafx.scene.control.SplitPane?> +<?import javafx.scene.layout.AnchorPane?> +<?import javafx.scene.layout.BorderPane?> +<?import javafx.scene.layout.HBox?> + +<BorderPane prefHeight="700.0" prefWidth="1200.0" stylesheets="@../../../ressourcen/style/Style.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="view.mainScene.MainSceneController"> + <top> + <MenuBar maxHeight="25.0" minHeight="25.0" BorderPane.alignment="CENTER"> + <menus> + <Menu mnemonicParsing="false" text="Datei"> + <items> + <MenuItem fx:id="menuFileNew" mnemonicParsing="false" onAction="#createFile" text="Neu" /> + <MenuItem fx:id="menuFileLoad" mnemonicParsing="false" onAction="#loadFile" text="Laden" /> + <MenuItem fx:id="menuFileSave" mnemonicParsing="false" onAction="#saveFile" text="Speichern" /> + <MenuItem fx:id="menuFileSaveAs" mnemonicParsing="false" onAction="#saveFileAs" text="Speichern unter" /> + <SeparatorMenuItem mnemonicParsing="false" /> + <MenuItem fx:id="menuFileQuit" mnemonicParsing="false" onAction="#quit" text="Beenden" /> + </items> + </Menu> + <Menu mnemonicParsing="false" text="Lampen"> + <items> + <MenuItem fx:id="menuFixtureAdd" mnemonicParsing="false" onAction="#createFixtures" text="Hinzufügen" /> + <MenuItem fx:id="menuFixtureEditRemove" mnemonicParsing="false" onAction="#editDeleteFixtures" text="Anpassen/Löschen" /> + </items> + </Menu> + <Menu mnemonicParsing="false" text="Gruppe"> + <items> + <MenuItem mnemonicParsing="false" onAction="#createGroup" text="Hinzufügen" /> + <MenuItem mnemonicParsing="false" onAction="#editDeleteGroup" text="Anpassen/Löschen" /> + </items> + </Menu> + <Menu mnemonicParsing="false" text="Lichtstimmung"> + <items> + <MenuItem mnemonicParsing="false" onAction="#createLightingMood" text="Hinzufügen" /> + <MenuItem mnemonicParsing="false" onAction="#editDeleteLightingMood" text="Anpassen/Löschen" /> + </items> + </Menu> + <Menu mnemonicParsing="false" text="Komposition"> + <items> + <MenuItem mnemonicParsing="false" onAction="#createComposition" text="Hinzufügen" /> + <MenuItem mnemonicParsing="false" onAction="#editDeleteComposition" text="Anpassen/Löschen" /> + </items> + </Menu> + <Menu mnemonicParsing="false" text="Interface"> + <items> + <MenuItem mnemonicParsing="false" onAction="#createNode" text="Node hinzufügen" /> + <MenuItem mnemonicParsing="false" onAction="#editDeleteNode" text="Node bearbeiten/löschen" /> + </items> + </Menu> + <Menu mnemonicParsing="false" text="Hilfe"> + <items> + <MenuItem mnemonicParsing="false" onAction="#testFixtures" text="Lampen testen" /> + <SeparatorMenuItem mnemonicParsing="false" /> + <MenuItem mnemonicParsing="false" onAction="#openOnlineHelp" text="Online Hilfe" /> + <SeparatorMenuItem mnemonicParsing="false" /> + <MenuItem mnemonicParsing="false" onAction="#openAboutKIWI" text="Über KIWI" /> + </items> + </Menu> + </menus> + </MenuBar> + </top> + <center> + <BorderPane BorderPane.alignment="CENTER"> + <left> + <BorderPane fx:id="groupInterfacePanel" maxWidth="300.0" minWidth="300.0" prefWidth="300.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" /> + </BorderPane.margin> + </BorderPane> + </left> + <center> + <SplitPane fx:id="compositionLightingMoodPanel" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" BorderPane.alignment="CENTER"> + <BorderPane.margin> + <Insets bottom="5.0" right="5.0" top="5.0" /> + </BorderPane.margin> + </SplitPane> + </center> + </BorderPane> + </center> + <bottom> + <AnchorPane maxHeight="20.0" minHeight="20.0" prefHeight="20.0" styleClass="footer" BorderPane.alignment="CENTER"> + <children> + <HBox layoutY="-178.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <Label text="Created by Sebastian Böttger"> + <padding> + <Insets left="5.0" right="5.0" /> + </padding> + </Label> + </children> + </HBox> + <HBox layoutX="10.0" layoutY="-168.0" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> + <children> + <Label text="KIWI V. 2.0"> + <padding> + <Insets left="5.0" right="5.0" /> + </padding> + </Label> + </children> + </HBox> + </children> + </AnchorPane> + </bottom> +</BorderPane> diff --git a/src/lightControlSoftware/src/view/mainScene/MainSceneController.java b/src/lightControlSoftware/src/view/mainScene/MainSceneController.java new file mode 100644 index 0000000000000000000000000000000000000000..cd89d5c7c20ffacd28e391b0b5cd6aaf5c185d91 --- /dev/null +++ b/src/lightControlSoftware/src/view/mainScene/MainSceneController.java @@ -0,0 +1,318 @@ +package view.mainScene; + +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.SplitPane; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.image.Image; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; + +import javafx.application.Platform; +import javafx.event.ActionEvent; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.MenuItem; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; +import view.composition.createPanel.CreateCompositionController; +import view.composition.editDeletePanel.EditDeleteCompositionController; +import view.composition.mainPanel.CompositionMainPanelController; +import view.fixture.createPanel.CreateFixtureController; +import view.fixture.editPanel.EditDeleteFixtureController; +import view.group.createPanel.CreateGroupController; +import view.group.editPanel.EditDeleteGroupController; +import view.group.mainPanel.GroupMainPanelController; +import view.lightController.mainPanel.LightControllerMainPanelController; +import view.lightingMood.createPanel.CreateLightingMoodController; +import view.lightingMood.editDeletePanel.EditDeleteLightingMoodController; +import view.lightingMood.mainPanel.LightingMoodMainPanelController; +import viewModel.KiwiViewModelHandler; + +public class MainSceneController { + @FXML + private MenuItem menuFileNew; + @FXML + private MenuItem menuFileLoad; + @FXML + private MenuItem menuFileSave; + @FXML + private MenuItem menuFileSaveAs; + @FXML + private MenuItem menuFileQuit; + @FXML + private MenuItem menuFixtureAdd; + @FXML + private MenuItem menuFixtureEditRemove; + @FXML + private BorderPane groupInterfacePanel; + @FXML + private SplitPane compositionLightingMoodPanel; + + private KiwiViewModelHandler viewModelHandler; + + public void init(KiwiViewModelHandler viewModelHandler) throws IOException { + this.viewModelHandler = viewModelHandler; + + FXMLLoader loaderCompositionPanel = new FXMLLoader(getClass().getResource("../composition/mainPanel/CompositionMainPanel.fxml")); + Parent compositionPanel = loaderCompositionPanel.load(); + CompositionMainPanelController compositionPanelController = loaderCompositionPanel.getController(); + compositionPanelController.init(viewModelHandler); + compositionLightingMoodPanel.getItems().add(compositionPanel); + + FXMLLoader loaderLightingMoodPanel = new FXMLLoader(getClass().getResource("../lightingMood/mainPanel/LightingMoodMainPanel.fxml")); + Parent lightingMoodPanel = loaderLightingMoodPanel.load(); + LightingMoodMainPanelController lightingMoodPanelController = loaderLightingMoodPanel.getController(); + lightingMoodPanelController.init(this.viewModelHandler); + compositionLightingMoodPanel.getItems().add(lightingMoodPanel); + + FXMLLoader loaderGroupPanel = new FXMLLoader(getClass().getResource("../group/mainPanel/GroupMainPanel.fxml")); + Parent groupPanel = loaderGroupPanel.load(); + GroupMainPanelController groupPanelController = loaderGroupPanel.getController(); + groupPanelController.init(viewModelHandler, lightingMoodPanelController, compositionPanelController); + groupInterfacePanel.setCenter(groupPanel); + + FXMLLoader loaderLightControllerPanel = new FXMLLoader(getClass().getResource("../lightController/mainPanel/LightControllerMainPanel.fxml")); + Parent lightControllerPanel = loaderLightControllerPanel.load(); + LightControllerMainPanelController lightControllerPanelController = loaderLightControllerPanel.getController(); + lightControllerPanelController.init(this.viewModelHandler.getArtNetControlleVM()); + groupInterfacePanel.setBottom(lightControllerPanel); + } + + // Event Listener on MenuItem[#menuFileNew].onAction + @FXML + public void createFile(ActionEvent event) { + this.viewModelHandler.clearRepros(); + } + // Event Listener on MenuItem[#menuFileLoad].onAction + @FXML + public void loadFile(ActionEvent event) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Funktion nicht verf�gbar."); + alert.setContentText("Die Funktion zum Laden von Files ist aktuell noch nicht verf�gbar."); + alert.showAndWait(); + } + // Event Listener on MenuItem[#menuFileSave].onAction + @FXML + public void saveFile(ActionEvent event) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Funktion nicht verf�gbar."); + alert.setContentText("Die Funktion zum Speichern von Files ist aktuell noch nicht verf�gbar."); + alert.showAndWait(); + } + // Event Listener on MenuItem[#menuFileSaveAs].onAction + @FXML + public void saveFileAs(ActionEvent event) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Funktion nicht verf�gbar."); + alert.setContentText("Die Funktion zum Speichern von Files ist aktuell noch nicht verf�gbar."); + alert.showAndWait(); + } + // Event Listener on MenuItem[#menuFileQuit].onAction + @FXML + public void quit(ActionEvent event) { + Platform.exit(); + } + // Event Listener on MenuItem[#menuFixtureAdd].onAction + @FXML + public void createFixtures(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../fixture/createPanel/CreateFixture.fxml")); + Parent createFixturePanel = loader.load(); + CreateFixtureController createFixtureController = loader.getController(); + Scene scene = new Scene(createFixturePanel); + Stage fixtureDialog = new Stage(); + createFixtureController.init(fixtureDialog, this.viewModelHandler); + fixtureDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + fixtureDialog.setScene(scene); + fixtureDialog.setTitle("Lampe hinzuf�gen"); + fixtureDialog.showAndWait(); + } + // Event Listener on MenuItem[#menuFixtureEditRemove].onAction + @FXML + public void editDeleteFixtures(ActionEvent event) throws IOException { + if(this.viewModelHandler.getFixtureRepositoryVM().fixturesRepositoryProperty().size() > 0) { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../fixture/editPanel/EditDeleteFixture.fxml")); + Parent editDeletefixturePanel = loader.load(); + EditDeleteFixtureController editDeleteFixtureController = loader.getController(); + Scene scene = new Scene(editDeletefixturePanel); + Stage fixtureDialog = new Stage(); + editDeleteFixtureController.init(fixtureDialog, this.viewModelHandler); + fixtureDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + fixtureDialog.setScene(scene); + fixtureDialog.setTitle("Lampe �ndern/l�schen"); + fixtureDialog.showAndWait(); + } else { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Es existieren keine Lampen."); + alert.setContentText("Bitte erstellen Sie zuerst eine Lampe."); + alert.showAndWait(); + } + } + // Event Listener on MenuItem.onAction + @FXML + public void createGroup(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../group/createPanel/CreateGroup.fxml")); + Parent createGroupPanel = loader.load(); + CreateGroupController createGroupController = loader.getController(); + Scene scene = new Scene(createGroupPanel); + Stage groupDialog = new Stage(); + createGroupController.init(groupDialog, viewModelHandler); + groupDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + groupDialog.setScene(scene); + groupDialog.setTitle("Gruppe hinzuf�gen"); + groupDialog.showAndWait(); + + + } + // Event Listener on MenuItem.onAction + @FXML + public void editDeleteGroup(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../group/editPanel/EditDeleteGroup.fxml")); + Parent editDeleteGroupPanel = loader.load(); + EditDeleteGroupController editDeleteGroupController = loader.getController(); + Scene scene = new Scene(editDeleteGroupPanel); + Stage groupDialog = new Stage(); + editDeleteGroupController.init(groupDialog, viewModelHandler); + groupDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + groupDialog.setScene(scene); + groupDialog.setTitle("Gruppe �ndern/l�schen"); + groupDialog.showAndWait(); + } + // Event Listener on MenuItem.onAction + @FXML + public void createLightingMood(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../lightingMood/createPanel/CreateLightingMood.fxml")); + Parent createLightingMoodPanel = loader.load(); + CreateLightingMoodController createLightingMoodController = loader.getController(); + Scene scene = new Scene(createLightingMoodPanel); + Stage lightingMoodDialog = new Stage(); + createLightingMoodController.init(lightingMoodDialog, this.viewModelHandler.getGroupRepositoryVM()); + lightingMoodDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + lightingMoodDialog.setScene(scene); + lightingMoodDialog.setTitle("Lichtstimmung erstellen"); + lightingMoodDialog.showAndWait(); + } + // Event Listener on MenuItem.onAction + @FXML + public void editDeleteLightingMood(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../lightingMood/editDeletePanel/EditDeleteLightingMood.fxml")); + Parent editDeleteLightingMoodPanel = loader.load(); + EditDeleteLightingMoodController editDeleteLightingMoodController = loader.getController(); + Scene scene = new Scene(editDeleteLightingMoodPanel); + Stage lightingMoodDialog = new Stage(); + editDeleteLightingMoodController.init(lightingMoodDialog, this.viewModelHandler); + lightingMoodDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + lightingMoodDialog.setScene(scene); + lightingMoodDialog.setTitle("Lichtstimmung bearbeiten/l�schen"); + lightingMoodDialog.showAndWait(); + } + // Event Listener on MenuItem.onAction + @FXML + public void createComposition(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../composition/createPanel/CreateComposition.fxml")); + Parent createCompositionPanel = loader.load(); + CreateCompositionController createCompositionController = loader.getController(); + Scene scene = new Scene(createCompositionPanel); + Stage compositionDialog = new Stage(); + createCompositionController.init(compositionDialog, this.viewModelHandler); + compositionDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + compositionDialog.setScene(scene); + compositionDialog.setTitle("Komposition erstellen"); + compositionDialog.showAndWait(); + createCompositionController = null; + loader = null; + + } + // Event Listener on MenuItem.onAction + @FXML + public void editDeleteComposition(ActionEvent event) throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource("../composition/editDeletePanel/EditDeleteComposition.fxml")); + Parent editDeleteCompositionPanel = loader.load(); + EditDeleteCompositionController editDeleteCompositionController = loader.getController(); + Scene scene = new Scene(editDeleteCompositionPanel); + Stage compositionDialog = new Stage(); + editDeleteCompositionController.init(compositionDialog, this.viewModelHandler); + compositionDialog.getIcons().add(new Image("images/Kiwi_Logo.png")); + compositionDialog.setScene(scene); + compositionDialog.setTitle("Komposition bearbeiten/l�schen"); + compositionDialog.showAndWait(); + editDeleteCompositionController = null; + loader = null; + } + // Event Listener on MenuItem.onAction + @FXML + public void createNode(ActionEvent event) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Funktion nicht verf�gbar."); + alert.setContentText("Die Funktion zum Speichern von Files ist aktuell noch nicht verf�gbar."); + alert.showAndWait(); + } + // Event Listener on MenuItem.onAction + @FXML + public void editDeleteNode(ActionEvent event) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Funktion nicht verf�gbar."); + alert.setContentText("Die Funktion zum Speichern von Files ist aktuell noch nicht verf�gbar."); + alert.showAndWait(); + } + // Event Listener on MenuItem.onAction + @FXML + public void testFixtures(ActionEvent event) { + Alert alert = new Alert(AlertType.WARNING); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("Warnung"); + alert.setHeaderText("Funktion nicht verf�gbar."); + alert.setContentText("Die Funktion zum Speichern von Files ist aktuell noch nicht verf�gbar."); + alert.showAndWait(); + } + // Event Listener on MenuItem.onAction + @FXML + public void openOnlineHelp(ActionEvent event) { + Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; + if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) { + try { + desktop.browse(new URI("https://gitlab.cvh-server.de/sboettger/kiwi-home-light-control-system")); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + // Event Listener on MenuItem.onAction + @FXML + public void openAboutKIWI(ActionEvent event) { + String headerText = "KIWI � 2024 Sebastian B�ttger\n"; + headerText += "Version: 2.0\n\n"; + headerText += "KIWI steht f�r KIWI (is a) Illumination Weeny Interface\n"; + headerText += "KIWI verwendet Art-Net 4.\n"; + headerText += "Art-Net� Designed by and Copyright Artistic Licence."; + + Alert alert = new Alert(AlertType.INFORMATION); + Stage stage = (Stage) alert.getDialogPane().getScene().getWindow(); + stage.getIcons().add(new Image("images/Kiwi_Logo.png")); + alert.setTitle("�ber KIWI"); + alert.setHeaderText(headerText); + alert.showAndWait(); + } +} diff --git a/src/lightControlSoftware/src/view/test/TestUI.java b/src/lightControlSoftware/src/view/test/TestUI.java new file mode 100644 index 0000000000000000000000000000000000000000..067c6b821302eaa1ca83d89fe366463c768da202 --- /dev/null +++ b/src/lightControlSoftware/src/view/test/TestUI.java @@ -0,0 +1,89 @@ +package view.test; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import javafx.application.Application; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.stage.Stage; + +public class TestUI extends Application{ + + protected final PropertyChangeSupport propertySupport = new PropertyChangeSupport(this); + private PropertyChangeListener fixtureListener; + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertySupport.addPropertyChangeListener(listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertySupport.removePropertyChangeListener(listener); + } + + public void printText(String text) { + System.out.println(text); + } + + public TestUI() { + this.fixtureListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("Test")) { + if((boolean) event.getNewValue()) { + printText("True"); + } else { + printText("False"); + } + } + } + }; + } + + + public static void main(String[] args) { + launch(args); + + } + + @Override + public void start(Stage stage) throws Exception { + + ObservableList<String> options = FXCollections.observableArrayList( + "Option 1", + "Option 2", + "Option 3" + ); + ComboBox<String> comboBox = new ComboBox<>(options); + comboBox.setOnAction(event -> { + propertySupport.firePropertyChange("Test", true, false); + }); + + Button buttonAnmelden = new Button("Anmelden"); + buttonAnmelden.setOnAction(event -> { + this.addPropertyChangeListener(fixtureListener); + }); + + Button buttonAbmelden = new Button("Abmelden"); + buttonAbmelden.setOnAction(event -> { + this.removePropertyChangeListener(fixtureListener); + }); + + + Pane root = new Pane(); + HBox hBox = new HBox(comboBox, buttonAnmelden, buttonAbmelden); + root.getChildren().add(hBox); + Scene scene = new Scene(root); + stage.setMinWidth(800); + stage.setMinHeight(625); + stage.setScene(scene); + stage.show(); + + } + +} diff --git a/src/lightControlSoftware/src/viewModel/KiwiViewModelHandler.java b/src/lightControlSoftware/src/viewModel/KiwiViewModelHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..ab47c1ea2e84e7b8fff937248c2d85e0b13ed0be --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/KiwiViewModelHandler.java @@ -0,0 +1,43 @@ +package viewModel; + +import model.KiwiModelHandler; +import viewModel.fixture.FixtureGroupRepositoryVM; +import viewModel.fixture.FixtureRepositoryVM; +import viewModel.group.GroupRepositoryVM; +import viewModel.lightController.ArtNetControlleVM; + +public class KiwiViewModelHandler { + private KiwiModelHandler modelHandler; + private GroupRepositoryVM groupRepositoryVM; + private FixtureRepositoryVM fixtureRepositoryVM; + private FixtureGroupRepositoryVM fixtureGroupRepositoryVM; + private ArtNetControlleVM artNetControlleVM; + + public KiwiViewModelHandler(KiwiModelHandler modelHandler) { + this.modelHandler = modelHandler; + groupRepositoryVM = new GroupRepositoryVM(KiwiModelHandler.getGroupReposirory()); + fixtureRepositoryVM = new FixtureRepositoryVM(KiwiModelHandler.getFixtureRepository()); + fixtureGroupRepositoryVM = new FixtureGroupRepositoryVM(KiwiModelHandler.getGroupReposirory()); + artNetControlleVM = new ArtNetControlleVM(KiwiModelHandler.getArtNetController()); + } + + public GroupRepositoryVM getGroupRepositoryVM() { + return groupRepositoryVM; + } + + public FixtureRepositoryVM getFixtureRepositoryVM() { + return fixtureRepositoryVM; + } + + public FixtureGroupRepositoryVM getFixtureGroupRepositoryVM() { + return fixtureGroupRepositoryVM; + } + + public ArtNetControlleVM getArtNetControlleVM() { + return this.artNetControlleVM; + } + + public void clearRepros() { + this.modelHandler.clearRepros(); + } +} diff --git a/src/lightControlSoftware/src/viewModel/composition/CompositionRepositoryVM.java b/src/lightControlSoftware/src/viewModel/composition/CompositionRepositoryVM.java new file mode 100644 index 0000000000000000000000000000000000000000..286c6ee596e2fce26578e4ca80da878db30b659d --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/composition/CompositionRepositoryVM.java @@ -0,0 +1,80 @@ +package viewModel.composition; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import model.lightingScene.composition.Composition; +import model.lightingScene.composition.CompositionRepository; + +public class CompositionRepositoryVM { + + private CompositionRepository compositionRepository; + private ObservableList<CompositionVM> compositionList; + private PropertyChangeListener compositionListener; + private CompositionRepositoryVM self = this; + + public CompositionRepositoryVM(CompositionRepository compositionRepository) { + this.compositionRepository = compositionRepository; + this.compositionList = FXCollections.observableArrayList(); + this.loadCompositions(); + + this.compositionListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("compositions")) { + if(event.getNewValue() != null) { + CompositionVM compositionVM = new CompositionVM((Composition) event.getNewValue()); + compositionVM.setCompositionRepositoryVM(self); + compositionList.add(compositionVM); + } else if(event.getOldValue() != null) { + Composition composition = (Composition) event.getOldValue(); + int compositionListIndex = -1; + for(int i = 0; i < compositionList.size(); i++) { + if(compositionList.get(i).getCompositionName().equals(composition.getName())) { + compositionListIndex = i; + break; + } + } + if(compositionListIndex != -1) { + compositionList.remove(compositionListIndex); + } + } + } + } + }; + this.compositionRepository.addPropertyChangeListener(compositionListener); + } + + public void loadCompositions() { + this.compositionRepository.getCompositionMap() + .forEach((String name, Composition composition) -> { + CompositionVM compositionVM = new CompositionVM(composition); + compositionVM.setCompositionRepositoryVM(this); + this.compositionList.add(compositionVM); + }); + } + + public CompositionVM getComposition(String name) { + return this.compositionList + .stream() + .filter( + compositionVM -> compositionVM.getCompositionName().equals(name)) + .findFirst() + .orElse(null); + } + + public ObservableList<CompositionVM> compositionListProperty() { + return this.compositionList; + } + + public void disselectedOtherCompositons(String compositionName) { + this.compositionList.forEach(compositionVM -> { + if(!compositionVM.getCompositionName().equals(compositionName)) { + compositionVM.setCompositionIsSeleceted(false); + } + }); + } + +} diff --git a/src/lightControlSoftware/src/viewModel/composition/CompositionVM.java b/src/lightControlSoftware/src/viewModel/composition/CompositionVM.java new file mode 100644 index 0000000000000000000000000000000000000000..03cd65424a88bd04c81ed710fb095db4c4a5534c --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/composition/CompositionVM.java @@ -0,0 +1,112 @@ +package viewModel.composition; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableMap; +import model.fixture.DmxValues; +import model.lightingScene.composition.Composition; +import viewModel.fixture.DmxValuesVM; + +public class CompositionVM { + + private Composition composition; + private StringProperty compositionName; + private BooleanProperty compositionIsActive; + private BooleanProperty selected = new SimpleBooleanProperty(false); + private ObservableMap<String, DmxValuesVM> compositionFixtureValues; + private PropertyChangeListener compositionListener; + private CompositionRepositoryVM compositionRepositoryVM; + + public CompositionVM(Composition composition) { + this.composition = composition; + this.compositionName = new SimpleStringProperty(composition.getName()); + this.compositionIsActive = new SimpleBooleanProperty(composition.isActive()); + this.compositionFixtureValues = FXCollections.observableHashMap(); + this.loadFixtureValues(); + this.compositionListener = new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("name")) { + compositionName.set((String)event.getNewValue()); + } else if(event.getPropertyName().equals("isActive")) { + compositionIsActive.set((boolean)event.getNewValue()); + } else if(event.getPropertyName().equals("setFixtureValues")) { + compositionFixtureValues.put((String)event.getOldValue(), new DmxValuesVM((DmxValues) event.getNewValue())); + } else if(event.getPropertyName().equals("removeFixtureValues")) { + compositionFixtureValues.remove((String)event.getOldValue()); + } + } + }; + this.composition.addPropertyChangeListener(compositionListener); + } + + public void setCompositionRepositoryVM(CompositionRepositoryVM compositionRepositoryVM) { + this.compositionRepositoryVM = compositionRepositoryVM; + } + + private void loadFixtureValues() { + this.composition.getFixtureValues().forEach((name, dmxValues) -> { + this.compositionFixtureValues.put(name, new DmxValuesVM(dmxValues)); + }); + + } + + public StringProperty compositionNameProperty() { + return this.compositionName; + } + + public BooleanProperty compositionIsActiveProperty() { + return this.compositionIsActive; + } + + public BooleanProperty selectedProperty() { + return this.selected; + } + + public void setCompositionName(String name) { + this.composition.setName(name); + } + + public void setCompositionIsSeleceted(boolean isSelected) { + if(isSelected && this.compositionRepositoryVM != null) { + this.compositionRepositoryVM.disselectedOtherCompositons(this.getCompositionName()); + } + this.selected.set(isSelected); + } + + public void activate() { + this.composition.activate(); + } + + public void deactivate() { + this.composition.deactivate(); + System.out.println(this.selected); + } + + public void setDmxValuesForFixture(String fixtureName, DmxValuesVM values) { + this.composition.setDmxValuesForFixture(fixtureName, values.getDmxValues()); + } + + public String getCompositionName() { + return this.compositionName.get(); + } + + public DmxValuesVM getDmxValuesForFixture(String fixtureName) { + return this.compositionFixtureValues.get(fixtureName); + } + + public Composition getComposition() { + return this.composition; + } + + public ObservableMap<String, DmxValuesVM> getCompositionFixtureValuesMap() { + return this.compositionFixtureValues; + } +} diff --git a/src/lightControlSoftware/src/viewModel/fixture/DmxValuesVM.java b/src/lightControlSoftware/src/viewModel/fixture/DmxValuesVM.java new file mode 100644 index 0000000000000000000000000000000000000000..9d3b3dc6dd193a2f77c4c5c269a23a452aa1e2b4 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/fixture/DmxValuesVM.java @@ -0,0 +1,89 @@ +package viewModel.fixture; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.nio.ByteBuffer; + +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleIntegerProperty; +import model.fixture.DmxValues; + +public class DmxValuesVM { + private DmxValues dmxValues; + private IntegerProperty mainIntensity; + private IntegerProperty strope; + private IntegerProperty red; + private IntegerProperty green; + private IntegerProperty blue; + private PropertyChangeListener dmxValueListener; + + public DmxValuesVM(DmxValues dmxValues) { + this.dmxValues = dmxValues; + this.mainIntensity = new SimpleIntegerProperty(Byte.toUnsignedInt(dmxValues.getIntensityMain())); + this.strope = new SimpleIntegerProperty(Byte.toUnsignedInt(dmxValues.getStropeRate())); + this.red = new SimpleIntegerProperty(Byte.toUnsignedInt(dmxValues.getIntensityRed())); + this.green = new SimpleIntegerProperty(Byte.toUnsignedInt(dmxValues.getIntensityGreen())); + this.blue = new SimpleIntegerProperty(Byte.toUnsignedInt(dmxValues.getIntensityBlue())); + this.dmxValueListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("intensityMain")) { + mainIntensity.setValue((int) event.getNewValue()); + } else if(event.getPropertyName().equals("stropeRate")) { + strope.setValue((int) event.getNewValue()); + } else if(event.getPropertyName().equals("intensityRed")) { + red.setValue((int) event.getNewValue()); + } else if(event.getPropertyName().equals("intensityGreen")) { + green.setValue((int) event.getNewValue()); + } else if(event.getPropertyName().equals("intensityBlue")) { + blue.setValue((int) event.getNewValue()); + } + } + }; + dmxValues.addPropertyChangeListener(dmxValueListener); + } + + public DmxValues getDmxValues() { + return this.dmxValues; + } + + public int getMainIntensity() { + return this.mainIntensity.get(); + } + + public void setMainIntensity(int mainIntensity) { + this.dmxValues.setIntensityMain(ByteBuffer.allocate(4).putInt(mainIntensity).get(3)); + } + + public int getStrope() { + return this.strope.get(); + } + + public void setStrope(int strope) { + this.dmxValues.setStropeRate(ByteBuffer.allocate(4).putInt(strope).get(3)); + } + + public int getRed() { + return this.red.get(); + } + + public void setRed(int red) { + this.dmxValues.setIntensityRed(ByteBuffer.allocate(4).putInt(red).get(3)); + } + + public int getGreen() { + return green.get(); + } + + public void setGreen(int green) { + this.dmxValues.setIntensityGreen(ByteBuffer.allocate(4).putInt(green).get(3)); + } + + public int getBlue() { + return blue.get(); + } + + public void setBlue(int blue) { + this.dmxValues.setIntensityBlue(ByteBuffer.allocate(4).putInt(blue).get(3)); + } +} diff --git a/src/lightControlSoftware/src/viewModel/fixture/FixtureGroupRepositoryVM.java b/src/lightControlSoftware/src/viewModel/fixture/FixtureGroupRepositoryVM.java new file mode 100644 index 0000000000000000000000000000000000000000..d45a7e073b98d6c282bfb245b8bfad550482e35e --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/fixture/FixtureGroupRepositoryVM.java @@ -0,0 +1,81 @@ +package viewModel.fixture; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import model.KiwiModelHandler; +import model.group.Group; +import model.group.GroupReposirory; + +public class FixtureGroupRepositoryVM { + private ObservableList<FixtureGroupVM> fixtureGroupsList; + private GroupReposirory groupRepository; + private PropertyChangeListener groupRepositoryListener; + + public FixtureGroupRepositoryVM(GroupReposirory groupRepository) { + this.groupRepository = groupRepository; + this.fixtureGroupsList = FXCollections.observableArrayList(); + this.loadGroups(); + this.groupRepositoryListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("groups")) { + if(event.getNewValue() != null) { + Group newGroup = (Group) event.getNewValue(); + addFixtureGroupToList(newGroup); + } else if(event.getOldValue() != null) { + Group oldGroup = (Group) event.getOldValue(); + int groupListIndex = -1; + for(int i = 0; i < fixtureGroupsList.size(); i++) { + if(fixtureGroupsList.get(i).getGroupName().equals(oldGroup.getName())) { + groupListIndex = i; + break; + } + } + if(groupListIndex != -1) { + fixtureGroupsList.remove(groupListIndex); + } + } + } + } + }; + this.groupRepository.addPropertyChangeListener(this.groupRepositoryListener); + } + + private void loadGroups() { + this.groupRepository.getGroupsMap().forEach((String name, Group group) -> { + this.addFixtureGroupToList(group); + }); + } + + private void addFixtureGroupToList(Group group) { + this.fixtureGroupsList.add(new FixtureGroupVM(group, this)); + } + + public ObservableList<FixtureGroupVM> fixtureGroupsListProperty() { + return this.fixtureGroupsList; + } + + public void newGroup(String name) { + this.groupRepository.addGroup(new Group(name, KiwiModelHandler.getLightController())); + } + + public void deleteGroup(String name) { + this.groupRepository.removeGroup(name); + } + + public void unselectOtherGroups(String groupName) { + this.fixtureGroupsList.forEach(fixtureGroupVM -> { + if(!fixtureGroupVM.getGroupName().equals(groupName) && fixtureGroupVM.getGroupSelected()) { + fixtureGroupVM.setGroupSelected(false); + } + }); + } + + @Override + protected void finalize() { + this.groupRepository.removePropertyChangeListener(this.groupRepositoryListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/fixture/FixtureGroupVM.java b/src/lightControlSoftware/src/viewModel/fixture/FixtureGroupVM.java new file mode 100644 index 0000000000000000000000000000000000000000..a761e99b5bd854433939d025ba688a7be7d4126a --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/fixture/FixtureGroupVM.java @@ -0,0 +1,104 @@ +package viewModel.fixture; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import model.group.Group; + +public class FixtureGroupVM { + + private IntegerProperty groupId; + private StringProperty groupName; + private BooleanProperty fixtureInGroup = new SimpleBooleanProperty(false); + private BooleanProperty groupSelected = new SimpleBooleanProperty(false); + private Group group; + private FixtureGroupRepositoryVM fixtureGroupRepositoryVM; + private FixtureRepositoryVM fixtureRepositoryVM; + private PropertyChangeListener groupListener; + + public FixtureGroupVM(Group group, FixtureGroupRepositoryVM fixtureGroupRepositoryVM) { + this.group = group; + this.fixtureRepositoryVM = new FixtureRepositoryVM(this.group.getFixtureRepository()); + this.fixtureGroupRepositoryVM = fixtureGroupRepositoryVM; + this.groupId = new SimpleIntegerProperty(group.getId()); + this.groupName = new SimpleStringProperty(group.getName()); + this.groupListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("name")) { + groupName.setValue((String)event.getNewValue()); + } + } + }; + + group.addPropertyChangeListener(this.groupListener); + } + + public String getGroupName() { + return this.groupName.get(); + } + + public void setGroupName(String groupName) { + this.group.setName(groupName); + } + + public boolean isFixtureInGroup() { + return this.fixtureInGroup.get(); + } + + public void setFixtureInGroup(boolean inGroup) { + this.fixtureInGroup.set(inGroup); + } + + public boolean getGroupSelected() { + return this.groupSelected.get(); + } + + public void setGroupSelected(boolean groupSelected) { + this.fixtureGroupRepositoryVM.unselectOtherGroups(this.getGroupName()); + this.groupSelected.set(groupSelected); + } + + public IntegerProperty groupIdProperty() { + return this.groupId; + } + + public StringProperty groupNameProperty() { + return this.groupName; + } + + public BooleanProperty fixtureInGroupProperty() { + return this.fixtureInGroup; + } + + public BooleanProperty groupSelectedProperty() { + return this.groupSelected; + } + + public FixtureGroupRepositoryVM getFixtureGroupRepositoryVM() { + return this.fixtureGroupRepositoryVM; + } + + public void addFixtureToGroup(FixtureVM fixtureVM) { + this.group.addFixture(fixtureVM.getFixture()); + } + + public void removeFixtureFromGroup(FixtureVM fixtureVM) { + this.group.removeFixture(fixtureVM.getFixture()); + } + + public FixtureRepositoryVM getFixtureRepositoryVM() { + return this.fixtureRepositoryVM; + } + + @Override + protected void finalize() { + this.group.removePropertyChangeListener(this.groupListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/fixture/FixtureRepositoryVM.java b/src/lightControlSoftware/src/viewModel/fixture/FixtureRepositoryVM.java new file mode 100644 index 0000000000000000000000000000000000000000..3df5bb1c72745d212f5c506dafeca7989a270c99 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/fixture/FixtureRepositoryVM.java @@ -0,0 +1,91 @@ +package viewModel.fixture; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import model.fixture.Fixture; +import model.fixture.FixtureRepository; + +public class FixtureRepositoryVM { + private ObservableList<FixtureVM> fixtureList; + private FixtureRepository fixtureRepository; + private PropertyChangeListener fixtureRepositoryListener; + + public FixtureRepositoryVM(FixtureRepository fixtureRepository) { + this.fixtureRepository = fixtureRepository; + this.fixtureList = FXCollections.observableArrayList(); + this.loadFixtures(); + + this.fixtureRepositoryListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("fixtures")) { + if(event.getNewValue() != null) { + Fixture newFixture = (Fixture) event.getNewValue(); + addFixtureToList(newFixture); + } else if(event.getOldValue() != null) { + Fixture oldFixture = (Fixture) event.getOldValue(); + int fixtureListIndex = -1; + for(int i = 0; i < fixtureList.size(); i++) { + if(fixtureList.get(i).getFixtureName().equals(oldFixture.getName())) { + fixtureListIndex = i; + break; + } + } + if(fixtureListIndex != -1) { + fixtureList.remove(fixtureListIndex); + } + } + } + } + }; + + this.fixtureRepository.addPropertyChangeListener(this.fixtureRepositoryListener); + } + + private void loadFixtures() { + this.fixtureRepository.getFixtureMap().forEach((String name, Fixture fixture) -> { + this.addFixtureToList(fixture); + }); + } + + private void addFixtureToList(Fixture fixture) { + FixtureVM newFixture = new FixtureVM(fixture, this); + this.fixtureList.add(newFixture); + } + + public ObservableList<FixtureVM> fixturesRepositoryProperty() { + return this.fixtureList; + } + + public void newFixture(String name, int address) { + this.fixtureRepository.addFixture(new Fixture(name, address)); + } + + public void deleteFixture(String name) { + this.fixtureRepository.removeFixture(name); + } + + public FixtureVM getFixtureVM(String name) { + return this.fixtureList.stream().filter(fixtureVM -> fixtureVM.getFixtureName().equals(name)).findFirst().orElse(null); + } + + public ObservableList<FixtureVM> fixtureListProperty() { + return this.fixtureList; + } + + public void unselectOtherFixtures(String fixtureName) { + this.fixtureList.forEach(fixtureVM -> { + if(!fixtureVM.getFixtureName().equals(fixtureName) && fixtureVM.getFixtureSelected()) { + fixtureVM.setFixtureSelected(false); + } + }); + } + + @Override + protected void finalize() { + this.fixtureRepository.removePropertyChangeListener(this.fixtureRepositoryListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/fixture/FixtureVM.java b/src/lightControlSoftware/src/viewModel/fixture/FixtureVM.java new file mode 100644 index 0000000000000000000000000000000000000000..30ae22b1ba0adb83058080cb24f6cf47d2f689c2 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/fixture/FixtureVM.java @@ -0,0 +1,114 @@ +package viewModel.fixture; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import model.fixture.Fixture; + +public class FixtureVM { + + private StringProperty fixtureName; + private IntegerProperty fixtureAddress; + private Fixture fixture; + private BooleanProperty fixtureInGroup = new SimpleBooleanProperty(false); + private BooleanProperty fixtureSelected = new SimpleBooleanProperty(false); + private PropertyChangeListener fixtureListener; + private FixtureRepositoryVM fixtureRepositoryVM; + private DmxValuesVM dmxValuesVM; + private String lightingMoodName = "Benutzerdefeniert"; + + public FixtureVM(Fixture fixture, FixtureRepositoryVM fixtureRepositoryVM) { + this.fixture = fixture; + this.fixtureRepositoryVM = fixtureRepositoryVM; + this.dmxValuesVM = new DmxValuesVM(fixture.getDmxValues()); + this.fixtureName = new SimpleStringProperty(this.fixture.getName()); + this.fixtureAddress = new SimpleIntegerProperty(this.fixture.getAddress()); + this.fixtureListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("name")) { + fixtureName.setValue((String)event.getNewValue()); + } else if(event.getPropertyName().equals("address")) { + fixtureAddress.setValue((Integer)event.getNewValue()); + } + } + }; + this.fixture.addPropertyChangeListener(this.fixtureListener); + } + + public String getFixtureName() { + return fixtureName.get(); + } + + public void setFixtureName(String fixtureName) { + this.fixture.setName(fixtureName); + } + + public int getFixtureAddress() { + return fixtureAddress.get(); + } + + public void setFixtureAddress(int fixtureAddress) { + this.fixture.setAddress(fixtureAddress); + } + + public boolean getFixtureSelected() { + return this.fixtureSelected.get(); + } + + public void setFixtureSelected(boolean selected) { + this.fixtureRepositoryVM.unselectOtherFixtures(this.fixtureName.get()); + this.fixtureSelected.set(selected); + } + + public void setFixtureInGroup(boolean inGroup) { + this.fixtureInGroup.set(inGroup); + } + + public boolean isFixtureInGroup() { + return this.fixtureInGroup.get(); + } + + public StringProperty fixtureNameProperty() { + return this.fixtureName; + } + + public IntegerProperty fixtureAddressProperty() { + return this.fixtureAddress; + } + + public Fixture getFixture() { + return this.fixture; + } + + public BooleanProperty fixtureInGroupProperty() { + return this.fixtureInGroup; + } + + public BooleanProperty fixtureSelectedProperty() { + return this.fixtureSelected; + } + + public DmxValuesVM getDmxValuesVM() { + return this.dmxValuesVM; + } + + public String getLightingMoodName() { + return lightingMoodName; + } + + public void setLightingMoodName(String lightingMoodName) { + this.lightingMoodName = lightingMoodName; + } + + @Override + protected void finalize() { + this.fixture.removePropertyChangeListener(this.fixtureListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/group/GroupRepositoryVM.java b/src/lightControlSoftware/src/viewModel/group/GroupRepositoryVM.java new file mode 100644 index 0000000000000000000000000000000000000000..67aa7714acf677e5d8146eed641c45e403b5f2da --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/group/GroupRepositoryVM.java @@ -0,0 +1,103 @@ +package viewModel.group; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import model.KiwiModelHandler; +import model.group.Group; +import model.group.GroupReposirory; + +public class GroupRepositoryVM { + private ObservableList<GroupVM> groupsList; + private GroupReposirory groupRepository; + private PropertyChangeListener groupRepositoryListener; + private ObjectProperty<GroupVM> currentSelectedGroup = new SimpleObjectProperty<>(); + + + public GroupRepositoryVM(GroupReposirory groupRepository) { + this.groupRepository = groupRepository; + this.groupsList = FXCollections.observableArrayList(); + this.loadGroups(); + this.groupRepositoryListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("groups")) { + if(event.getNewValue() != null) { + Group newGroup = (Group) event.getNewValue(); + addGroupToList(newGroup); + } else if(event.getOldValue() != null) { + Group oldGroup = (Group) event.getOldValue(); + int groupListIndex = -1; + for(int i = 0; i < groupsList.size(); i++) { + if(groupsList.get(i).getGroupName().equals(oldGroup.getName())) { + groupListIndex = i; + break; + } + } + if(groupListIndex != -1) { + groupsList.remove(groupListIndex); + } + } + } + } + }; + this.groupRepository.addPropertyChangeListener(this.groupRepositoryListener); + } + + private void loadGroups() { + this.groupRepository.getGroupsMap().forEach((String name, Group group) -> { + this.addGroupToList(group); + }); + } + + private void addGroupToList(Group group) { + this.groupsList.add(new GroupVM(group, this)); + } + + public ObservableList<GroupVM> groupsListProperty() { + return this.groupsList; + } + + public void newGroup(String name) { + this.groupRepository.addGroup(new Group(name, KiwiModelHandler.getLightController())); + } + + public void deleteGroup(String name) { + this.groupRepository.removeGroup(name); + } + + public GroupVM getGroupVM(String name) { + return this.groupsList.stream() + .filter(groupVM -> groupVM + .getGroupName().equals(name)) + .findFirst() + .orElse(null); + } + + public void unselectOtherGroups(String groupName) { + this.currentSelectedGroup.set(this.groupsList + .stream() + .filter(groupVM -> groupVM.getGroupName() == groupName) + .findFirst() + .orElse(null)); + + this.groupsList.forEach(groupVM -> { + if(!groupVM.getGroupName().equals(groupName) && groupVM.getGroupSelected()) { + groupVM.setGroupSelected(false); + } + }); + } + + public ObjectProperty<GroupVM> currentSelectedGroupProperty() { + return this.currentSelectedGroup; + } + + @Override + protected void finalize() { + this.groupRepository.removePropertyChangeListener(this.groupRepositoryListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/group/GroupVM.java b/src/lightControlSoftware/src/viewModel/group/GroupVM.java new file mode 100644 index 0000000000000000000000000000000000000000..52b721d3e28b3173ae06c3dd5c40ce0b63036e41 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/group/GroupVM.java @@ -0,0 +1,200 @@ +package viewModel.group; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import model.group.Group; +import viewModel.composition.CompositionRepositoryVM; +import viewModel.composition.CompositionVM; +import viewModel.fixture.FixtureRepositoryVM; +import viewModel.fixture.FixtureVM; +import viewModel.lightingMood.LightingMoodRepositoryVM; +import viewModel.lightingMood.LightingMoodVM; + +public class GroupVM { + + public static enum State{ + OFF, + MID, + ON + }; + + private IntegerProperty groupId; + private StringProperty groupName; + private ObjectProperty<State> groupState = new SimpleObjectProperty<>(State.OFF); + private BooleanProperty groupSelected = new SimpleBooleanProperty(false); + private Group group; + private GroupRepositoryVM groupRepositoryVM; + private PropertyChangeListener groupListener; + private LightingMoodRepositoryVM lightingMoodRepositoryVM; + private CompositionRepositoryVM compositionRepositoryVM; + private FixtureRepositoryVM fixtureRepositoryVM; + + public GroupVM(Group group, GroupRepositoryVM groupRepositoryVM) { + this.group = group; + this.groupRepositoryVM = groupRepositoryVM; + this.fixtureRepositoryVM = new FixtureRepositoryVM(this.group.getFixtureRepository()); + this.lightingMoodRepositoryVM = new LightingMoodRepositoryVM(this.group.getLightingMoodRepository()); + this.compositionRepositoryVM = new CompositionRepositoryVM(this.group.getCompositionRepository()); + this.groupId = new SimpleIntegerProperty(group.getId()); + this.groupName = new SimpleStringProperty(group.getName()); + this.groupListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("name")) { + groupName.setValue((String)event.getNewValue()); + } else if(event.getPropertyName().equals("currentState")) { + switch((model.group.Group.State) event.getNewValue()) { + case AKTIV: + groupState.setValue(State.ON); + break; + case PARTAKTIV: + groupState.setValue(State.MID); + break; + case DEAKTIV: + groupState.setValue(State.OFF); + break; + } + } + } + }; + + group.addPropertyChangeListener(this.groupListener); + this.groupState.addListener((object, oldValue, newValue) -> { + this.setGroupState((State) newValue); + }); + } + + public String getGroupName() { + return this.groupName.get(); + } + + public void setGroupName(String groupName) { + this.group.setName(groupName); + } + + public State getGroupState() { + return this.groupState.get(); + } + + public void setGroupState(State groupState) { + switch(groupState) { + case ON: + this.group.activate(); + break; + case MID: + this.group.setCurrentState(model.group.Group.State.PARTAKTIV); + break; + case OFF: + this.group.deactivate(); + break; + } + } + + public boolean getGroupSelected() { + return this.groupSelected.get(); + } + + public void setGroupSelected(boolean groupSelected) { + if(groupSelected) { + this.groupRepositoryVM.unselectOtherGroups(this.getGroupName()); + } + this.groupSelected.set(groupSelected); + } + + public FixtureRepositoryVM getFixtureRepositoryVM() { + return this.fixtureRepositoryVM; + } + + public LightingMoodRepositoryVM getLightingMoodRepositoryVM() { + return this.lightingMoodRepositoryVM; + } + + public CompositionRepositoryVM getCompositionRepositoryVM() { + return this.compositionRepositoryVM; + } + + public IntegerProperty groupIdProperty() { + return this.groupId; + } + + public StringProperty groupNameProperty() { + return this.groupName; + } + + public ObjectProperty<State> groupStateProperty() { + return this.groupState; + } + + public BooleanProperty groupSelectedProperty() { + return this.groupSelected; + } + + public Group getGroup() { + return this.group; + } + + public void addFixture(FixtureVM fixtureVM) { + this.group.addFixture(fixtureVM.getFixture()); + } + + public void removeFixture(FixtureVM fixtureVM) { + this.group.removeFixture(fixtureVM.getFixture()); + } + + public boolean isFixtureInGroup(String name) { + if(this.group.getFixtureRepository().getFixture(name) == null) { + return false; + } else { + return true; + } + } + + public void addLightingMood(LightingMoodVM lightingMoodVM) { + this.group.addLightingMood(lightingMoodVM.getLightingMood()); + } + + public void activateLightingMood(LightingMoodVM lightingMoodVM) { + this.group.activateLightingMood( + this.lightingMoodRepositoryVM + .getLightingMood(lightingMoodVM.getLightingMoodName()).getLightingMood()); + } + + public void deactivateLightingMood(LightingMoodVM lightingMoodVM) { + this.group.deactivateLightingMood( + this.lightingMoodRepositoryVM + .getLightingMood(lightingMoodVM.getLightingMoodName()).getLightingMood()); + } + + public void removeLightingMood(LightingMoodVM ligtingMoodVM) { + this.group.removeLightingMood(ligtingMoodVM.getLightingMood()); + } + + public void addComposition(CompositionVM compositionVM) { + this.group.addComposition(compositionVM.getComposition()); + } + + public void activateComposition(CompositionVM compositionVM) { + this.group.activateComposition(compositionVM.getComposition()); + } + + public void deactivateComposition(CompositionVM compositionVM) { + this.group.deactivateComposition(compositionVM.getComposition()); + } + + public void removeComposition(CompositionVM composition) { + this.group.removeComposition(composition.getComposition()); + } + + @Override + protected void finalize() { + this.group.removePropertyChangeListener(this.groupListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/lightController/ArtNetControlleVM.java b/src/lightControlSoftware/src/viewModel/lightController/ArtNetControlleVM.java new file mode 100644 index 0000000000000000000000000000000000000000..b2e4350a93810ec572788c8f10104d4ee8e8129b --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/lightController/ArtNetControlleVM.java @@ -0,0 +1,26 @@ +package viewModel.lightController; + +import model.lightController.artNet.ArtNetController; + +public class ArtNetControlleVM { + private ArtNetNodeRepositoryVM artNetNodeRepositoryVM; + private ArtNetController artNetController; + + public ArtNetControlleVM(ArtNetController artNetController) { + this.artNetController = artNetController; + this.artNetNodeRepositoryVM = new ArtNetNodeRepositoryVM(this.artNetController.getNodeRepository()); + } + + public void connectToNodes() { + this.artNetController.connectToNodes(); + } + + public void disconnectFromNodes() { + this.artNetController.disconnectNodes(); + } + + public ArtNetNodeRepositoryVM getArtNetNodeRepositoryVM() { + return this.artNetNodeRepositoryVM; + } +} + diff --git a/src/lightControlSoftware/src/viewModel/lightController/ArtNetNodeRepositoryVM.java b/src/lightControlSoftware/src/viewModel/lightController/ArtNetNodeRepositoryVM.java new file mode 100644 index 0000000000000000000000000000000000000000..ddacad1737f19ec57048815e4befddf4d13b6678 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/lightController/ArtNetNodeRepositoryVM.java @@ -0,0 +1,54 @@ +package viewModel.lightController; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleObjectProperty; +import model.lightController.artNet.artNetNode.ArtNetNodeRepository; +import viewModel.group.GroupVM.State; + +public class ArtNetNodeRepositoryVM { + private ArtNetNodeRepository artNetNodeRepository; + private BooleanProperty nodesConnected = new SimpleBooleanProperty(false); + private ObjectProperty<State> connectState = new SimpleObjectProperty<>(State.OFF); + private PropertyChangeListener nodeRepositoryListener; + + public ArtNetNodeRepositoryVM(ArtNetNodeRepository artNetNodeRepository) { + this.artNetNodeRepository = artNetNodeRepository; + this.nodeRepositoryListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("nodesConnected")) { + nodesConnected.set((boolean) event.getNewValue()); + if((boolean) event.getNewValue()) { + connectState.set(State.ON); + } else { + if(connectState.get() == State.OFF) { + connectState.set(State.MID); + } else { + connectState.set(State.OFF); + } + + } + } + } + }; + + this.artNetNodeRepository.addPropertyChangeListener(this.nodeRepositoryListener); + } + + public boolean isNodesConneted() { + return this.nodesConnected.get(); + } + + public BooleanProperty nodesConnectedProperty() { + return this.nodesConnected; + } + + public ObjectProperty<State> connectStateProperty() { + return this.connectState; + } +} diff --git a/src/lightControlSoftware/src/viewModel/lightingMood/LightingMoodRepositoryVM.java b/src/lightControlSoftware/src/viewModel/lightingMood/LightingMoodRepositoryVM.java new file mode 100644 index 0000000000000000000000000000000000000000..e334787411077b52da7baf5b38ccd726bc227bf8 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/lightingMood/LightingMoodRepositoryVM.java @@ -0,0 +1,94 @@ +package viewModel.lightingMood; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import model.lightingScene.lightingMood.LightingMood; +import model.lightingScene.lightingMood.LightingMoodRepository; + +public class LightingMoodRepositoryVM { + private ObservableList<LightingMoodVM> lightingMoodList; + private LightingMoodRepository lightingMoodRepository; + private PropertyChangeListener lightingMoodListener; + private LightingMoodRepositoryVM self = this; + + + public LightingMoodRepositoryVM(LightingMoodRepository lightingMoodRepository) { + this.lightingMoodRepository = lightingMoodRepository; + this.lightingMoodList = FXCollections.observableArrayList(); + this.loadLightingMoods(); + this.lightingMoodListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("lightingMoods")) { + if(event.getNewValue() != null) { + LightingMoodVM lightingMoodVM = new LightingMoodVM((LightingMood) event.getNewValue()); + lightingMoodVM.setLightingMoodRepositoryVM(self); + lightingMoodList.add(lightingMoodVM); + } else if(event.getOldValue() != null) { + LightingMood lightingMood = (LightingMood) event.getOldValue(); + int lightingMoodListIndex = -1; + for(int i = 0; i < lightingMoodList.size(); i++) { + if(lightingMoodList.get(i).getLightingMoodName().equals(lightingMood.getName())) { + lightingMoodListIndex = i; + break; + } + } + if(lightingMoodListIndex != -1) { + lightingMoodList.remove(lightingMoodListIndex); + } + } + } + } + }; + + this.lightingMoodRepository.addPropertyChangeListener(this.lightingMoodListener); + } + + private void loadLightingMoods() { + this.lightingMoodRepository.getLightingMoodMap() + .forEach((String name, LightingMood lightingMood) -> { + LightingMoodVM lightingMoodVM = new LightingMoodVM(lightingMood); + lightingMoodVM.setLightingMoodRepositoryVM(this); + this.lightingMoodList.add(lightingMoodVM); + + }); + } + + public void addLightingMood(LightingMoodVM lightingMoodVM) { + lightingMoodVM.setLightingMoodRepositoryVM(this); + this.lightingMoodRepository.addLightingMood(lightingMoodVM.getLightingMood()); + } + + public void removeLightingMood(LightingMoodVM lightingMoodVM) { + this.lightingMoodRepository.removeLightingMood(lightingMoodVM.getLightingMoodName()); + } + + public LightingMoodVM getLightingMood(String name) { + return this.lightingMoodList + .stream() + .filter( + lightingMood -> lightingMood.getLightingMoodName() + .equals(name)) + .findFirst() + .orElse(null); + } + + public ObservableList<LightingMoodVM> lightingMoodListProperty() { + return this.lightingMoodList; + } + + public void disableOtherLightingMoods(String name) { + this.lightingMoodList.forEach(lightingMoodVM -> { + if(!lightingMoodVM.getLightingMoodName().equals(name)) { + lightingMoodVM.LightingMoodIsSelectedProperty().set(false); + } + }); + } + + @Override + protected void finalize() { + this.lightingMoodRepository.removePropertyChangeListener(this.lightingMoodListener); + } +} diff --git a/src/lightControlSoftware/src/viewModel/lightingMood/LightingMoodVM.java b/src/lightControlSoftware/src/viewModel/lightingMood/LightingMoodVM.java new file mode 100644 index 0000000000000000000000000000000000000000..489618d96b8c3ad9dcc2240c60f8b70eee3abaf3 --- /dev/null +++ b/src/lightControlSoftware/src/viewModel/lightingMood/LightingMoodVM.java @@ -0,0 +1,225 @@ +package viewModel.lightingMood; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import model.lightingScene.lightingMood.LightingMood; +import viewModel.fixture.DmxValuesVM; + +public class LightingMoodVM { + private LightingMood lightingMood; + private StringProperty lightingMoodName; + private BooleanProperty lightingMoodIsActive; + private BooleanProperty lightingMoodIsSelected = new SimpleBooleanProperty(false); + private IntegerProperty lightingMoodMainIntensity; + private IntegerProperty lightingMoodStrope; + private IntegerProperty lightingMoodRed; + private IntegerProperty lightingMoodGreen; + private IntegerProperty lightingMoodBlue; + private PropertyChangeListener lightingMoodListener; + private PropertyChangeListener dmxValueListener; + private LightingMoodRepositoryVM lightingMoodRepositoryVM; + + + public LightingMoodVM(LightingMood lightingMood) { + this.lightingMood = lightingMood; + this.lightingMoodName = new SimpleStringProperty(lightingMood.getName()); + this.lightingMoodIsActive = new SimpleBooleanProperty(lightingMood.isActive()); + this.lightingMoodMainIntensity = new SimpleIntegerProperty(Byte.toUnsignedInt(lightingMood.getDmxValues().getIntensityMain())); + this.lightingMoodStrope = new SimpleIntegerProperty(Byte.toUnsignedInt(lightingMood.getDmxValues().getStropeRate())); + this.lightingMoodRed = new SimpleIntegerProperty(Byte.toUnsignedInt(lightingMood.getDmxValues().getIntensityRed())); + this.lightingMoodGreen = new SimpleIntegerProperty(Byte.toUnsignedInt(lightingMood.getDmxValues().getIntensityGreen())); + this.lightingMoodBlue = new SimpleIntegerProperty(Byte.toUnsignedInt(lightingMood.getDmxValues().getIntensityBlue())); + + this.setupListener(); + this.lightingMood.addPropertyChangeListener(lightingMoodListener); + this.lightingMood.getDmxValues().addPropertyChangeListener(dmxValueListener); + } + + public void setLightingMoodRepositoryVM(LightingMoodRepositoryVM lightingMoodRepositoryVM) { + this.lightingMoodRepositoryVM = lightingMoodRepositoryVM; + } + + public LightingMood getLightingMood() { + return lightingMood; + } + + public String getLightingMoodName() { + return lightingMoodName.get(); + } + + public void setLightingMoodName(String name) { + this.lightingMood.setName(name); + } + + public boolean getLightingMoodIsActive() { + return lightingMoodIsActive.get(); + } + + public boolean getLightingMoodIsSelected() { + return lightingMoodIsSelected.get(); + } + + public void setLightingMoodIsSelected(boolean isSelected) { + if(isSelected && this.lightingMoodRepositoryVM != null) { + this.lightingMoodRepositoryVM.disableOtherLightingMoods(this.getLightingMoodName()); + } + this.lightingMoodIsSelected.set(isSelected); + } + + public int getLightingMoodMainIntensity() { + return lightingMoodMainIntensity.get(); + } + + public void setLightingMoodMainIntensity(int mainIntensity) { + this.lightingMood.getDmxValues().setIntensityMain((byte) mainIntensity); + } + + public int getLightingMoodStrope() { + return lightingMoodStrope.get(); + } + + public void setLightingMoodStrope(int strope) { + this.lightingMood.getDmxValues().setStropeRate((byte) strope); + } + + public int getLightingMoodRed() { + return lightingMoodRed.get(); + } + + public void setLightingMoodRed(int red) { + this.lightingMood.getDmxValues().setIntensityRed((byte) red); + } + + public int getLightingMoodGreen() { + return lightingMoodGreen.get(); + } + + public void setLightingMoodGreen(int green) { + this.lightingMood.getDmxValues().setIntensityGreen((byte) green); + } + + public int getLightingMoodBlue() { + return lightingMoodBlue.get(); + } + + public void setLightingMoodBlue(int blue) { + this.lightingMood.getDmxValues().setIntensityBlue((byte) blue); + } + + public StringProperty LightingMoodNameProperty() { + return lightingMoodName; + } + + public BooleanProperty LightingMoodIsActiveProperty() { + return lightingMoodIsActive; + } + + public BooleanProperty LightingMoodIsSelectedProperty() { + return lightingMoodIsSelected; + } + + public IntegerProperty LightingMoodMainIntensityProperty() { + return lightingMoodMainIntensity; + } + + public IntegerProperty LightingMoodStropeProperty() { + return lightingMoodStrope; + } + + public IntegerProperty LightingMoodRedProperty() { + return lightingMoodRed; + } + + public IntegerProperty LightingMoodGreenProperty() { + return lightingMoodGreen; + } + + public IntegerProperty LightingMoodBlueProperty() { + return lightingMoodBlue; + } + + public PropertyChangeListener LightingMoodListenerProperty() { + return lightingMoodListener; + } + + public void activate() { + this.lightingMood.activate(); + } + + public void deactivate() { + this.lightingMood.deactivate(); + } + + public void setupListener() { + this.lightingMoodListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("name")) { + lightingMoodName.set((String) event.getNewValue()); + } else if(event.getPropertyName().equals("isActive")) { + lightingMoodIsActive.set((boolean) event.getNewValue()); + } + } + }; + + this.dmxValueListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if(event.getPropertyName().equals("intensityMain")) { + lightingMoodMainIntensity.set((int)event.getNewValue()); + } else if(event.getPropertyName().equals("stropeRate")) { + lightingMoodStrope.set((int)event.getNewValue()); + } else if(event.getPropertyName().equals("intensityRed")) { + lightingMoodRed.set((int)event.getNewValue()); + } else if(event.getPropertyName().equals("intensityGreen")) { + lightingMoodGreen.set((int)event.getNewValue()); + } else if(event.getPropertyName().equals("intensityBlue")) { + lightingMoodBlue.set((int)event.getNewValue()); + } + } + }; + + this.lightingMoodName.addListener((object, oldValue, newValue) -> { + this.lightingMood.setName(newValue); + }); + + this.lightingMoodIsActive.addListener((object, oldValue, newValue) -> { + if(newValue) { + this.lightingMood.activate(); + } else { + this.lightingMood.deactivate(); + } + }); + + this.lightingMoodMainIntensity.addListener((object, oldValue, newValue) -> { + this.lightingMood.getDmxValues().setIntensityMain(newValue.byteValue()); + }); + + this.lightingMoodStrope.addListener((object, oldValue, newValue) -> { + this.lightingMood.getDmxValues().setStropeRate(newValue.byteValue()); + }); + + this.lightingMoodRed.addListener((object, oldValue, newValue) -> { + this.lightingMood.getDmxValues().setIntensityRed(newValue.byteValue()); + }); + + this.lightingMoodGreen.addListener((object, oldValue, newValue) -> { + this.lightingMood.getDmxValues().setIntensityGreen(newValue.byteValue()); + }); + + this.lightingMoodBlue.addListener((object, oldValue, newValue) -> { + this.lightingMood.getDmxValues().setIntensityBlue(newValue.byteValue()); + }); + } + + public DmxValuesVM getDmxValuesVM() { + return new DmxValuesVM(this.lightingMood.getDmxValues()); + } + +} diff --git a/src/lightControlUnit/ArtNetController/ArtCommands.h b/src/lightControlUnit/ArtNetController/ArtCommands.h new file mode 100644 index 0000000000000000000000000000000000000000..0f46e123941e4e068761f8c3715364e4165d58a2 --- /dev/null +++ b/src/lightControlUnit/ArtNetController/ArtCommands.h @@ -0,0 +1,48 @@ +struct activatePresetStructure +{ + char *presetId = "presetId"; +}; + +struct deactivatePresetStructure +{ + char *presetId = "presetId"; +}; + +struct clearPresetStructure +{ + char *presetId = "presetId"; +}; + +struct setPresetStructure +{ + char *presetId = "presetId"; + char *groupId = "groupId"; + char *channel = "channel"; + char *value = "value"; +}; + +struct setChannelStateStructure +{ + char *channel = "channel"; + char *isActive = "isActive"; +}; + +struct activateGroupStructure +{ + char *groupId = "groupId"; +}; + +struct deactivateGroupStructure +{ + char *groupId = "groupId"; +}; + +struct presetActivatedStructure +{ + char *presetId = "presetId"; +}; + +struct presetDeactivatedStructure +{ + char *presetId = "presetId"; +}; \ No newline at end of file diff --git a/src/lightControlUnit/ArtNetController/ArtNetController.cpp b/src/lightControlUnit/ArtNetController/ArtNetController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a793257200df45b6dfff7c447381c6c50036201d --- /dev/null +++ b/src/lightControlUnit/ArtNetController/ArtNetController.cpp @@ -0,0 +1,676 @@ +#include "ArtNetController.h" + +//******************************************************** +//**Art-Net™ Designed by and Copyright Artistic Licence.** +//******************************************************** + +ArtNetController::ArtNetController(){} + +ArtNetController::ArtNetController (DmxController* dmxController, PresetRepository* presetRepository) +{ + this->startUdp(); + this->dmxController = dmxController; + this->presetRepository = presetRepository; + + for(int i = 0; i < 4;i++) + { + this->controllerIpAddress[i] = 0x00; + } +} + +int ArtNetController::startUdp() +{ + this->mac[0] = MAC_ADDRESS_PART_01; + this->mac[1] = MAC_ADDRESS_PART_02; + this->mac[2] = MAC_ADDRESS_PART_03; + this->mac[3] = MAC_ADDRESS_PART_04; + this->mac[4] = MAC_ADDRESS_PART_05; + this->mac[5] = MAC_ADDRESS_PART_06; + + if (Ethernet.begin(this->mac) == 0) + { + Serial.println("Failed to configure Ethernet using DHCP"); + if (Ethernet.hardwareStatus() == EthernetNoHardware) + { + Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); + } + else if (Ethernet.linkStatus() == LinkOFF) + { + Serial.println("Ethernet cable is not connected."); + } + } + + this->nodeIpAddress[0] = Ethernet.localIP()[0]; + this->nodeIpAddress[1] = Ethernet.localIP()[1]; + this->nodeIpAddress[2] = Ethernet.localIP()[2]; + this->nodeIpAddress[3] = Ethernet.localIP()[3]; + + this->udp.begin(UDP_PORT_ADRESS); +} + +bool ArtNetController::checkArtNetHeader(uint8_t udpData[]) +{ + bool headerFound = true; + uint8_t artNetHeader[8] = {'A','r','t','-','N','e','t',0x00}; + for(int i = 0; i < 8; i++) + { + if(udpData[i] != artNetHeader[i]) + { + headerFound = false; + } + } + + return headerFound; +} + +uint8_t *ArtNetController::getPresetStatus() +{ + uint8_t *presetsStatus = new uint8_t[NUMBER_OF_PRESETS]; + for(int i = 0; i < NUMBER_OF_PRESETS; i++) + { + presetsStatus[i] = this->presetRepository->getPresetState(i); + } + + return presetsStatus; +} + +void ArtNetController::sendPresetActivated(int presetId) +{ + String commandString = String(ART_COM_PA) + "={\"presetId\":" + String(presetId) + "}"; + uint16_t length = commandString.length(); + char command[length]; + commandString.toCharArray(command, length+1); + this->sendArtCommand(command, length); +} + +void ArtNetController::sendPresetDeactivated(int presetId) +{ + String commandString = String(ART_COM_PD) + "={\"presetId\":" + String(presetId) + "}"; + uint16_t length = commandString.length(); + char command[length]; + commandString.toCharArray(command, length+1); + this->sendArtCommand(command, length); +} + +void ArtNetController::listenToArtNet() +{ + + int packetSize = this->udp.parsePacket(); + if(packetSize >= 14) + { + // read the packet into packetBufferRead + uint8_t *packetBufferRead = new uint8_t[packetSize]; + this->udp.read(packetBufferRead,packetSize); + + if(this->checkArtNetHeader(packetBufferRead)) + { + uint16_t opCode = (((uint16_t)packetBufferRead[9] << 8) + packetBufferRead[8]); + switch(opCode) + { + case OP_POLL: + // save ip address from controller + for(int i = 0; i < 4;i++) + { + this->controllerIpAddress[i] = this->udp.remoteIP()[i]; + } + this->sendArtPollReply(); + break; + + case OP_COMMAND: + this->processArtCommand(packetBufferRead, packetSize); + break; + + case OP_DATA_REQUEST: + // save ip address from controller + for(int i = 0; i < 4;i++) + { + this->controllerIpAddress[i] = this->udp.remoteIP()[i]; + } + this->processArtDataRequest(packetBufferRead, packetSize); + break; + + case OP_DMX: + this->processArtDmx(packetBufferRead, packetSize); + } + } + } +} + +ArtCommand ArtNetController::parseToArtCommand(uint8_t updData[], int length) +{ + ArtCommand artCommand; + + if(length >= 16) + { + // protocoll version + artCommand.ProtVerHi = updData[10]; + artCommand.ProtVerLo = updData[11]; + + // esta manifacture + artCommand.EstaManHi = updData[12]; + artCommand.EstaManLo = updData[13]; + + // lengths + artCommand.Length = (((uint16_t)updData[14] << 8) + updData[15]); + + if(artCommand.Length > 0) + { + artCommand.Data = new char[artCommand.Length + 1]; + for(int i = 0; i < artCommand.Length; i++) + { + artCommand.Data[i] = (char)updData[16 + i]; + } + artCommand.Data[artCommand.Length] = '\0'; + } + } + + return artCommand; +} + +ArtDataRequest ArtNetController::parseToArtDataRequest(uint8_t updData[], int length) +{ + ArtDataRequest artDataRequest; + if(length >= 18) + { + // protocoll version + artDataRequest.ProtVerHi = updData[10]; + artDataRequest.ProtVerLo = updData[11]; + + // esta manifacture + artDataRequest.EstaManHi = updData[12]; + artDataRequest.EstaManLo = updData[13]; + + // oem + artDataRequest.OemHi = updData[14]; + artDataRequest.OemLo = updData[15]; + + // request code + artDataRequest.RequestCode = (((uint16_t)updData[16] << 8) + updData[17]); + } + + return artDataRequest; +} + +ArtDmx ArtNetController::parseToArtDmx(uint8_t updData[], int length) +{ + ArtDmx artDmx; + if(length >= 18) + { + // protocoll version + artDmx.ProtVerHi = updData[10]; + artDmx.ProtVerLo = updData[11]; + + // sequence + artDmx.Sequence = updData[12]; + + // pysical input port + artDmx.Physical = updData[13]; + + // art-net address + artDmx.SubUni = updData[14]; + artDmx.Net = updData[15]; + + artDmx.Length = (((uint16_t)updData[16] << 8) + updData[17]); + + if(artDmx.Length > 0) + { + artDmx.Data = new uint8_t[artDmx.Length]; + for(int i = 0; i < artDmx.Length; i++) + { + artDmx.Data[i] = updData[18+i]; + } + } + } + + return artDmx; +} + +void ArtNetController::parseFromArtPollReply(ArtPollReply artPollReply, uint8_t* udpSendData, int length) +{ + if(length >= 207) + { + // id + for(int i = 0; i<8; i++) + { + udpSendData[i] = artPollReply.Id[i]; + } + + // op code + udpSendData[8] = artPollReply.OpCode; + udpSendData[9] = artPollReply.OpCode >> 8; + + // node ip + for(int i= 0; i < 4; i++) + { + udpSendData[10+i] = artPollReply.IpAddress[i]; + } + + // port + udpSendData[14] = artPollReply.Port; + udpSendData[15] = artPollReply.Port>> 8; + + // version info + udpSendData[16] = artPollReply.VersInfoH; + udpSendData[17] = artPollReply.VersInfoL; + + // net address + udpSendData[18] = artPollReply.NetSwitch; + + // sub net address + udpSendData[19] = artPollReply.SubSwitch; + + // oem + udpSendData[20] = artPollReply.OemHi; + udpSendData[21] = artPollReply.OemLo; + + // ubea version + udpSendData[22] = artPollReply.UbeaVersion; + + // status + udpSendData[23] = artPollReply.Status1; + + // esta + udpSendData[24] = artPollReply.EstaManLo; + udpSendData[25] = artPollReply.EstaManHi; + + // port name + for (int i = 0; i < 18; i++) + { + udpSendData[26+i] = artPollReply.PortName[i]; + } + + // long name + for (int i = 0; i < 64; i++) + { + udpSendData[44+i] = artPollReply.LongName[i]; + } + + // node report + for (int i = 0; i < 64; i++) + { + udpSendData[108+i] = artPollReply.NodeReport[i]; + } + + // number of ports + udpSendData[172] = artPollReply.NumPortsHi; + udpSendData[173] = artPollReply.NumPortsLo; + + // port type + for (int i = 0; i < 4; i++) + { + udpSendData[174+i] = artPollReply.PortTypes[i]; + } + + // good inputs + for (int i = 0; i < 4; i++) + { + udpSendData[178+i] = artPollReply.GoodInput[i]; + } + + // good output A + for (int i = 0; i < 4; i++) + { + udpSendData[182+i] = artPollReply.GoodOutputA[i]; + } + + // sw in + for (int i = 0; i < 4; i++) + { + udpSendData[186+i] = artPollReply.SwIn[i]; + } + + // sw out + for (int i = 0; i < 4; i++) + { + udpSendData[190+i] = artPollReply.SwOut[i]; + } + + // prio acn + udpSendData[194] = artPollReply.AcnPriority; + + // sw macro + udpSendData[195] = artPollReply.SwMacro; + + // sw remote + udpSendData[196] = artPollReply.SwRemote; + + // spare + for (int i = 0; i < 3; i++) + { + udpSendData[197+i] = 0x00; + } + + // style + udpSendData[200] = artPollReply.Style; + + // mac address + for (int i = 0; i < 6; i++) + { + udpSendData[201+i] = artPollReply.Mac[i]; + } + } + if(length >= 208) + { + // bind ip + for (int i = 0; i < 4; i++) + { + udpSendData[207+i] = artPollReply.BindIp[i]; + } + } + if(length >= 212) + { + // bind index + udpSendData[211] = artPollReply.BindIndex; + } + if(length >= 213) + { + // status 2 + udpSendData[212] = artPollReply.Status2; + } + if(length >= 214) + { + // good output b + for (int i = 0; i < 4; i++) + { + udpSendData[213+i] = artPollReply.GoodOutputB[i]; + } + } + if(length >= 218) + { + // status 3 + udpSendData[217] = artPollReply.Status3; + } + if(length >= 219) + { + // default responder uid + for (int i = 0; i < 6; i++) + { + udpSendData[218+i] = artPollReply.DefaulRespUID[i]; + } + } + if(length >= 225) + { + // user data + udpSendData[224] = artPollReply.UserHi; + udpSendData[225] = artPollReply.UserLo; + } + if(length >= 227) + { + // user data + udpSendData[226] = artPollReply.RefreshRateHi; + udpSendData[227] = artPollReply.RefreshRateLo; + + // filler + for (int i = 0; i < 8; i++) + { + udpSendData[228+i] = 0x00; + } + + } +} + +void ArtNetController::parseFromArtCommand(ArtCommand artCommand, uint8_t* udpSendData, int length) +{ + if(length > 16) + { + // id + for(int i = 0; i<8; i++) + { + udpSendData[i] = artCommand.Id[i]; + } + + // op code + udpSendData[8] = artCommand.OpCode; + udpSendData[9] = artCommand.OpCode >> 8; + + // protocol version + udpSendData[10] = artCommand.ProtVerHi; + udpSendData[11] = artCommand.ProtVerLo; + + // esta manifactur + udpSendData[12] = artCommand.EstaManHi; + udpSendData[13] = artCommand.EstaManLo; + + // length + udpSendData[14] = artCommand.Length >> 8; + udpSendData[15] = artCommand.Length; + + for(int i=0; i < artCommand.Length; i++) + { + udpSendData[16+i] = artCommand.Data[i]; + } + } +} + +void ArtNetController::parseFromArtDataReply(ArtDataReply artDataReply, uint8_t* udpSendData, int length) +{ + if(length >= 20) + { + // id + for(int i = 0; i<8; i++) + { + udpSendData[i] = artDataReply.Id[i]; + } + + // op code + udpSendData[8] = artDataReply.OpCode; + udpSendData[9] = artDataReply.OpCode >> 8; + + // protocol version + udpSendData[10] = artDataReply.ProtVerHi; + udpSendData[11] = artDataReply.ProtVerLo; + + // esta manifactur + udpSendData[12] = artDataReply.EstaManHi; + udpSendData[13] = artDataReply.EstaManLo; + + // oem + udpSendData[14] = artDataReply.OemHi; + udpSendData[15] = artDataReply.OemLo; + + // request code + udpSendData[16] = artDataReply.RequestCode >> 8; + udpSendData[17] = artDataReply.RequestCode; + + // peyload lengths + udpSendData[18] = artDataReply.PayLength >> 8; + udpSendData[19] = artDataReply.PayLength; + + for(int i=0; i < artDataReply.PayLength; i++) + { + udpSendData[20+i] = artDataReply.PayLoad[i]; + } + } +} + +void ArtNetController::sendArtPollReply() +{ + int packageSize = 236; + + ArtPollReply artPollReply; + // set controller ip + for(int i = 0; i < 4; i++) + { + artPollReply.IpAddress[i] = this->nodeIpAddress[i]; + } + + char* longName = "KIWI (is a) Illumination Weeny Interface"; + + // set long name + bool endOfLine = false; + for(int i = 0; i < 64; i++) + { + if(longName[i] != '\0' && !endOfLine) + { + artPollReply.LongName[i] = longName[i]; + } + else + { + endOfLine = true; + artPollReply.LongName[i] = 0x00; + } + } + + // set node report + for(int i = 0; i < 64; i++) + { + artPollReply.NodeReport[i] = 0x00; + } + + // set mac address + for(int i = 0; i < 6; i++) + { + artPollReply.Mac[i] = this->mac[i]; + } + + uint8_t updSendData[packageSize]; + this->parseFromArtPollReply(artPollReply, updSendData, packageSize); + + + IPAddress remoteIp = IPAddress(this->controllerIpAddress); + this->udp.beginPacket(remoteIp, UDP_PORT_ADRESS); + this->udp.write(updSendData, packageSize); + this->udp.endPacket(); +} + +void ArtNetController::sendArtCommand(char *message, uint16_t length) +{ + ArtCommand artCommand; + artCommand.Length = length; + artCommand.Data = message; + int packageSize = 16 + length; + + if(this->controllerIpAddress[0] != 0x00) + { + uint8_t updSendData[packageSize]; + this->parseFromArtCommand(artCommand, updSendData, packageSize); + + IPAddress remoteIp = IPAddress(this->controllerIpAddress); + this->udp.beginPacket(remoteIp, UDP_PORT_ADRESS); + this->udp.write(updSendData, packageSize); + this->udp.endPacket(); + } +} + +void ArtNetController::sendArtDataReply(uint16_t dataRequstCode) +{ + ArtDataReply artDataReply; + artDataReply.RequestCode = dataRequstCode; + int packageSize = 20; + uint8_t productUrl[PRODUCT_URL_LENGTHS]; + for(int i = 0; i < PRODUCT_URL_LENGTHS; i++) + { + productUrl[i] = String(PRODUCT_URL).charAt(i); + } + + switch(dataRequstCode) + { + case DR_POLL: + artDataReply.PayLength = 0x0000; + artDataReply.PayLoad = nullptr; + break; + case DR_URL_PRODUCT: + artDataReply.PayLength = PRODUCT_URL_LENGTHS; + artDataReply.PayLoad = productUrl; + packageSize += PRODUCT_URL_LENGTHS; + break; + case DR_URL_USER_GUIDE: + artDataReply.PayLength = PRODUCT_URL_LENGTHS; + artDataReply.PayLoad = productUrl; + packageSize += PRODUCT_URL_LENGTHS; + break; + case DR_URL_SUPPORT: + artDataReply.PayLength = PRODUCT_URL_LENGTHS; + artDataReply.PayLoad = productUrl; + packageSize += PRODUCT_URL_LENGTHS; + break; + case DR_URL_PERS_UDR: + artDataReply.PayLength = 0x0000; + artDataReply.PayLoad = nullptr; + break; + break; + case DR_URL_PERS_GDTF: + artDataReply.PayLength = 0x0000; + artDataReply.PayLoad = nullptr; + break; + break; + case DR_PRESET_STATUS: + artDataReply.PayLength = (uint16_t)NUMBER_OF_PRESETS; + artDataReply.PayLoad = getPresetStatus(); + packageSize += NUMBER_OF_PRESETS; + break; + } + + uint8_t updSendData[packageSize]; + this->parseFromArtDataReply(artDataReply, updSendData, packageSize); + + IPAddress remoteIp = IPAddress(this->controllerIpAddress); + this->udp.beginPacket(remoteIp, UDP_PORT_ADRESS); + this->udp.write(updSendData, packageSize); + this->udp.endPacket(); +} + +void ArtNetController::processArtCommand(uint8_t updData[], int length) +{ + ArtCommand artCommand = this->parseToArtCommand(updData, length); + + char *commandString = strtok(artCommand.Data, "&"); + while (commandString != NULL) { + String command = String(commandString).substring(0, String(commandString).indexOf('=')); + int commandValuelength = (String(commandString).substring(String(commandString).indexOf('=')+1)).length() + 1; + char commandValue[commandValuelength]; + String(commandString).substring(String(commandString).indexOf('=')+1).toCharArray(commandValue, commandValuelength); + deserializeJson(doc, commandValue, commandValuelength); + + if(command.equals(ART_COM_AP)) + { + this->presetRepository->activatePreset(doc[activatePresetStructure().presetId]); + } + else if(command.equals(ART_COM_DP)) + { + this->presetRepository->deactivatePreset(doc[deactivatePresetStructure().presetId]); + } + else if(command.equals(ART_COM_CP)) + { + this->presetRepository->clearPreset(doc[clearPresetStructure().presetId]); + } + else if(command.equals(ART_COM_SP)) + { + this->presetRepository->setPresetGroupId(doc[setPresetStructure().presetId], doc[setPresetStructure().groupId]); + this->presetRepository->setPresetChannelValue(doc[setPresetStructure().presetId], doc[setPresetStructure().channel], doc[setPresetStructure().value]); + } + else if(command.equals(ART_COM_SC)) + { + this->dmxController->setChannelStatus(doc[setChannelStateStructure().isActive], doc[setChannelStateStructure().channel]); + this->presetRepository->updatePresetState(); + } + else if(command.equals(ART_COM_AG)) + { + this->presetRepository->activateGroup(doc[activateGroupStructure().groupId]); + } + else if(command.equals(ART_COM_DG)) + { + this->presetRepository->deactivateGroup(doc[deactivateGroupStructure().groupId]); + } + + commandString = strtok(NULL, "&"); + } +} + +void ArtNetController::processArtDataRequest(uint8_t updData[], int length) +{ + ArtDataRequest artDataRequest = this->parseToArtDataRequest(updData, length); + this->sendArtDataReply(artDataRequest.RequestCode); +} + +void ArtNetController::processArtDmx(uint8_t updData[], int length) +{ + ArtDmx artDmx = this->parseToArtDmx(updData, length); + if(artDmx.SubUni == 0x00 && artDmx.Net == 0x00) + { + for(int i = 0; i<artDmx.Length; i++) + { + this->dmxController->setChannelValue(i+1, artDmx.Data[i]); + } + } +} \ No newline at end of file diff --git a/src/lightControlUnit/ArtNetController/ArtNetController.h b/src/lightControlUnit/ArtNetController/ArtNetController.h new file mode 100644 index 0000000000000000000000000000000000000000..71c7d7cc90c83df7d4ca712f936488685577f827 --- /dev/null +++ b/src/lightControlUnit/ArtNetController/ArtNetController.h @@ -0,0 +1,49 @@ +#ifndef ArtNetController_h +#define ArtNetController_h + +#include <SPI.h> +#include <Arduino.h> +#include <Ethernet.h> +#include <EthernetUdp.h> +#include <ArduinoJson.h> +#include "./ArtCommands.h" +#include "../config/config.h" +#include "./ArtNetPackageTypes.h" +#include "../DmxController/DmxController.h" +#include "../PresetRepository/PresetRepository.h" + +class ArtNetController +{ + private: + PresetRepository* presetRepository; + DmxController* dmxController; + uint8_t mac[6]; + uint8_t nodeIpAddress[4]; + uint8_t controllerIpAddress[4] = {0x00, 0x00, 0x00, 0x00}; + EthernetUDP udp; + int startUdp(); + bool checkArtNetHeader(uint8_t udpData[]); + uint8_t *getPresetStatus(); + StaticJsonDocument<50> doc; + + public: + ArtNetController(); + ArtNetController(DmxController* dmxController, PresetRepository* presetRepository); + void sendPresetActivated(int presetId); + void sendPresetDeactivated(int presetId); + void listenToArtNet(); + ArtPoll parseToArtPoll(uint8_t updData[], int length); + ArtCommand parseToArtCommand(uint8_t updData[], int length); + ArtDataRequest parseToArtDataRequest(uint8_t updData[], int length); + ArtDmx parseToArtDmx(uint8_t updData[], int length); + void parseFromArtPollReply(ArtPollReply artPollReply, uint8_t* udpSendData, int length); + void parseFromArtCommand(ArtCommand artCommand, uint8_t* udpSendData, int length); + void parseFromArtDataReply(ArtDataReply artDataReply, uint8_t* udpSendData, int length); + void sendArtPollReply(); + void sendArtCommand(char *message, uint16_t length); + void sendArtDataReply(uint16_t dataRequstCode); + void processArtCommand(uint8_t updData[], int length); + void processArtDataRequest(uint8_t updData[], int length); + void processArtDmx(uint8_t updData[], int length); +}; +#endif \ No newline at end of file diff --git a/src/lightControlUnit/ArtNetController/ArtNetPackageTypes.h b/src/lightControlUnit/ArtNetController/ArtNetPackageTypes.h new file mode 100644 index 0000000000000000000000000000000000000000..a32927f71308c0ffe0ae1a509dc17457c5aebcef --- /dev/null +++ b/src/lightControlUnit/ArtNetController/ArtNetPackageTypes.h @@ -0,0 +1,148 @@ +#include <Arduino.h> + +// op codes +#define OP_POLL 0x2000 +#define OP_POLL_REPLY 0x2100 +#define OP_COMMAND 0x2400 +#define OP_DATA_REQUEST 0x2700 +#define OP_DATA_REPLY 0x2800 +#define OP_DMX 0x5000 + +// request codes +#define DR_POLL 0x0000 +#define DR_URL_PRODUCT 0x0001 +#define DR_URL_USER_GUIDE 0x0002 +#define DR_URL_SUPPORT 0x0003 +#define DR_URL_PERS_UDR 0x0004 +#define DR_URL_PERS_GDTF 0x0005 +#define DR_PRESET_STATUS 0x8000 + +// artCommand commands +#define ART_COM_AP "activatePreset" +#define ART_COM_DP "deactivatePreset" +#define ART_COM_CP "clearPreset" +#define ART_COM_SP "setPreset" +#define ART_COM_SC "setChannelState" +#define ART_COM_AG "activateGroup" +#define ART_COM_DG "deactivateGroup" +#define ART_COM_PA "presetActivated" +#define ART_COM_PD "presetDeactivated" + +// information +#define PORT_NAME "KIWI" +#define LONG_NAME "KIWI (is a) Illumination Weeny Interface" + +struct ArtPoll +{ + uint8_t Id[8] = {'A','r','t','-','N','e','t',0x00}; + uint16_t OpCode = OP_POLL; + uint8_t ProtVerHi = 0x00; + uint8_t ProtVerLo = 0x0e; // Version 14 + uint8_t Flags = 0x00; + uint8_t DiagPriority = 0x00; + uint8_t TargetPortAddressTopHi = 0x00; + uint8_t TargetPortAddressTopLo = 0x00; + uint8_t TargetPortAddressBottomHi = 0x00; + uint8_t TargetPortAddressBottomLo = 0x00; + uint8_t EstaManHi = 0x00; + uint8_t EstaManLo = 0x00; + uint8_t OemHi = 0xff; + uint8_t OemLo = 0xff; +}; + +struct ArtPollReply +{ + uint8_t Id[8] = {'A','r','t','-','N','e','t',0x00}; + uint16_t OpCode = OP_POLL_REPLY; + uint8_t IpAddress[4] = {0x00, 0x00, 0x00, 0x00}; + uint16_t Port = 0x1936; + uint8_t VersInfoH = 0x00; + uint8_t VersInfoL = 0x01; + uint8_t NetSwitch = 0x00; + uint8_t SubSwitch = 0x00; + uint8_t OemHi = 0xff; + uint8_t OemLo = 0xff; + uint8_t UbeaVersion = 0x00; + uint8_t Status1 = 0x00; + uint8_t EstaManLo = 0x00; + uint8_t EstaManHi = 0x00; + uint8_t PortName[18] = {'K', 'I', 'W', 'I', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t LongName[64]; + uint8_t NodeReport[64]; + uint8_t NumPortsHi = 0x00; + uint8_t NumPortsLo = 0x01; + uint8_t PortTypes[4] = {0x80, 0x00, 0x00, 0x00}; + uint8_t GoodInput[4] = {0x04, 0x04, 0x04, 0x04}; + uint8_t GoodOutputA [4] = {0x80, 0x00, 0x00, 0x00}; + uint8_t SwIn[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t SwOut[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t AcnPriority = 0x00; + uint8_t SwMacro = 0x00; + uint8_t SwRemote = 0x00; + uint8_t Style = 0x00; + uint8_t Mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t BindIp[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t BindIndex = 0x00; + uint8_t Status2 = 0x00; + uint8_t GoodOutputB[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t Status3 = 0x00; + uint8_t DefaulRespUID[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t UserHi = 0x00; + uint8_t UserLo = 0x00; + uint8_t RefreshRateHi = 0x00; + uint8_t RefreshRateLo = 0x2C; +}; + +struct ArtCommand +{ + uint8_t Id[8] = {'A','r','t','-','N','e','t',0x00}; + uint16_t OpCode = OP_COMMAND; + uint8_t ProtVerHi = 0x00; + uint8_t ProtVerLo = 0x0e; // Version 14; + uint8_t EstaManHi = 0x00; + uint8_t EstaManLo = 0x00; + uint16_t Length = 0x0000; + char *Data; +}; + +struct ArtDataRequest +{ + uint8_t Id[8] = {'A','r','t','-','N','e','t',0x00}; + uint16_t OpCode = OP_DATA_REQUEST; + uint8_t ProtVerHi = 0x00; + uint8_t ProtVerLo = 0x0e; // Version 14; + uint8_t EstaManHi = 0x00; + uint8_t EstaManLo = 0x00; + uint8_t OemHi = 0xff; + uint8_t OemLo = 0xff; + uint16_t RequestCode = 0x0000; +}; + +struct ArtDataReply +{ + uint8_t Id[8] = {'A','r','t','-','N','e','t',0x00}; + uint16_t OpCode = OP_DATA_REPLY; + uint8_t ProtVerHi = 0x00; + uint8_t ProtVerLo = 0x0e; // Version 14; + uint8_t EstaManHi = 0x00; + uint8_t EstaManLo = 0x00; + uint8_t OemHi = 0xff; + uint8_t OemLo = 0xff; + uint16_t RequestCode = 0x0000; + uint16_t PayLength = 0x0000; + uint8_t *PayLoad; +}; + +struct ArtDmx +{ + uint8_t Id[8] = {'A','r','t','-','N','e','t',0x00}; + uint16_t OpCode = OP_DMX; + uint8_t ProtVerHi = 0x00; + uint8_t ProtVerLo = 0x0e; // Version 14; + uint8_t Sequence = 0x00; + uint8_t Physical = 0x00; + uint8_t SubUni = 0x00; + uint8_t Net = 0x00; + uint16_t Length = 0x0200; + uint8_t *Data; +}; \ No newline at end of file diff --git a/src/lightControlUnit/DmxChannel/DmxChannel.h b/src/lightControlUnit/DmxChannel/DmxChannel.h new file mode 100644 index 0000000000000000000000000000000000000000..4363f695bd98a84c8bf17f9b90d8fa3c37180415 --- /dev/null +++ b/src/lightControlUnit/DmxChannel/DmxChannel.h @@ -0,0 +1,6 @@ +struct DmxChannel +{ + public: + bool isUsed; + uint8_t value; +}; \ No newline at end of file diff --git a/src/lightControlUnit/DmxController/DmxController.cpp b/src/lightControlUnit/DmxController/DmxController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b65c5200617ec27553013334351bfa7c1d165758 --- /dev/null +++ b/src/lightControlUnit/DmxController/DmxController.cpp @@ -0,0 +1,36 @@ +#include "DmxController.h" + +DmxController::DmxController() +{ + DmxSimple.usePin(DMX_PINOUT); + DmxSimple.maxChannel(MAX_DMX_CHANNEL); + activChannel = Set(true); +} + +void DmxController::setChannelValue(int channel, unsigned char value) +{ + DmxSimple.write(channel, value); +} + +void DmxController::setChannelValue(bool isActive, int channel, unsigned char value) +{ + this->setChannelStatus(isActive, channel); + this->setChannelValue(channel, value); +} + +void DmxController::setChannelStatus(bool isActive, int channel) +{ + if(isActive) + { + this->activChannel.add(channel); + } + else + { + this->activChannel.sub(channel); + } +} + +Set DmxController::getActiveChannel() +{ + return this->activChannel; +} \ No newline at end of file diff --git a/src/lightControlUnit/DmxController/DmxController.h b/src/lightControlUnit/DmxController/DmxController.h new file mode 100644 index 0000000000000000000000000000000000000000..ae57d11cfd6acc99cef7b06f71c4e0ea9776f247 --- /dev/null +++ b/src/lightControlUnit/DmxController/DmxController.h @@ -0,0 +1,21 @@ +#ifndef DmxController_h +#define DmxController_h +#include <DmxSimple.h> +#include "set.h" +#include "../config/config.h" + +class DmxController +{ + private: + unsigned char dmxOut[MAX_DMX_CHANNEL]; + Set activChannel; + + + public: + DmxController(); + void setChannelValue(int channel, unsigned char value); + void setChannelValue(bool isActive, int channel, unsigned char value); + void setChannelStatus(bool isActive, int channel); + Set getActiveChannel(); +}; +#endif \ No newline at end of file diff --git a/src/lightControlUnit/Preset/Preset.cpp b/src/lightControlUnit/Preset/Preset.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb30fbe6df439ce458f2a93e18a4dff7026cfff8 --- /dev/null +++ b/src/lightControlUnit/Preset/Preset.cpp @@ -0,0 +1,131 @@ +#include "Preset.h" + +Preset::Preset() {} + +Preset::Preset(int eepromAdress, PresetLed presetLed) +{ + this->eepromAdress = eepromAdress; + this->presetLed = presetLed; + this->clearPreset(); + this->usedChannel = Set(true); +} + +void Preset::loadPresetData() +{ + PresetStoredInfromation data; + EEPROM.get(this->eepromAdress, data); + this->setState(data.state); + this->setGroupId(data.groupId); + for(int i = 0; i < MAX_DMX_CHANNEL; i++) + { + this->dmxChannels[i] = data.dmxChannels[i]; + if(data.dmxChannels[i].isUsed) + { + this->usedChannel.add(i+1); + } + } +} + +void Preset::savePresetData() +{ + PresetStoredInfromation dataWrite; + dataWrite.state = this->state; + dataWrite.groupId = this->groupId; + for (uint8_t i = 0; i < 100; i++) + { + dataWrite.dmxChannels[i] = this->dmxChannels[i]; + } + EEPROM.put(this->eepromAdress, dataWrite); +} + +void Preset::setState(uint8_t state) +{ + this->state = state; + switch(state) + { + case P_DEAKTIV: + this->presetLed.setColor(false, false, false); + break; + case P_ACTIVE: + this->presetLed.setColor(false, true, false); + break; + case P_PART_ACTIVE: + this->presetLed.setColor(false, false, true); + break; + } +} + +void Preset::setChannelValue(int channel, uint8_t value) +{ + DmxChannel dmxChannel = {true, value}; + if(channel <= MAX_DMX_CHANNEL) + { + this->usedChannel.add(channel); + this->dmxChannels[channel-1] = dmxChannel; + } +} + +void Preset::setGroupId(uint8_t groupId) +{ + this->groupId = groupId; +} + +uint8_t Preset::getState() +{ + return this->state; +} + +void Preset::clearPreset() +{ + this->usedChannel.clear(); + for(int i = 0; i<MAX_DMX_CHANNEL; i++) + { + DmxChannel emptyChannel = {false, 0}; + this->dmxChannels[i] = emptyChannel; + } + this->groupId = DEFAULT_GROUP_ID; +} + +void Preset::updateState(Set activeChannel, bool aktiveGroupMember) +{ + bool isNonActive = false; + bool isPartActive = false; + int channel; + + for(int i = 0; i < this->usedChannel.count(); i++) { + channel = i==0 ? this->usedChannel.first() : this->usedChannel.next(); + + if(activeChannel.has(channel)) + { + isPartActive = true; + } + else + { + isNonActive = true; + } + } + + if (isNonActive && !isPartActive) + { + this->setState(P_DEAKTIV); + } + else if (isNonActive && isPartActive) + { + this->setState(P_PART_ACTIVE); + } + else if(isPartActive && this->state != P_ACTIVE && !aktiveGroupMember) + { + this->setState(P_PART_ACTIVE); + } + this->savePresetData(); +} + +uint8_t Preset::getGroupId() +{ + return this->groupId; +} + +DmxChannel* Preset::getDmxChannel() +{ + return this->dmxChannels; +} \ No newline at end of file diff --git a/src/lightControlUnit/Preset/Preset.h b/src/lightControlUnit/Preset/Preset.h new file mode 100644 index 0000000000000000000000000000000000000000..24b11326fff38d3e9840a540ea8a4ea403010457 --- /dev/null +++ b/src/lightControlUnit/Preset/Preset.h @@ -0,0 +1,33 @@ +#ifndef Preset_h +#define Preset_h + +#include <Arduino.h> +#include <EEPROM.h> +#include "set.h" +#include "../config/config.h" +#include "../PresetStoredInfromation/PresetStoredInfromation.h" +#include "../PresetLed/PresetLed.h" + +class Preset:PresetStoredInfromation +{ + private: + int eepromAdress; + PresetLed presetLed; + Set usedChannel; + + public: + Preset(); + Preset(int eepromAdress, PresetLed presetLed); + uint8_t getState(); + uint8_t getGroupId(); + DmxChannel* getDmxChannel(); + void setState(uint8_t state); + void setGroupId(uint8_t groupId); + void setChannelValue(int channel, uint8_t value); + void clearPreset(); + void loadPresetData(); + void savePresetData(); + void updateState(Set activeChannel, bool aktiveGroupMember); + +}; +#endif \ No newline at end of file diff --git a/src/lightControlUnit/PresetLed/PresetLed.cpp b/src/lightControlUnit/PresetLed/PresetLed.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0698af6e632caf1b18c72c51290d629637b5d0ab --- /dev/null +++ b/src/lightControlUnit/PresetLed/PresetLed.cpp @@ -0,0 +1,20 @@ +#include "PresetLed.h" + +PresetLed::PresetLed(){} + +PresetLed::PresetLed(int redPinOut, int greenPinOut, int bluePinOut) +{ + this->redPinOut = redPinOut; + this->greenPinOut = greenPinOut; + this->bluePinOut = bluePinOut; + + pinMode(this->redPinOut, OUTPUT); + pinMode(this->greenPinOut, OUTPUT); + pinMode(this->bluePinOut, OUTPUT); +} + +void PresetLed::setColor(bool red, bool green, bool blue) { + digitalWrite(this->redPinOut, red ? HIGH: LOW); + digitalWrite(this->greenPinOut, green ? HIGH: LOW); + digitalWrite(this->bluePinOut, blue ? HIGH: LOW); +} \ No newline at end of file diff --git a/src/lightControlUnit/PresetLed/PresetLed.h b/src/lightControlUnit/PresetLed/PresetLed.h new file mode 100644 index 0000000000000000000000000000000000000000..95ed7f3e2cea2dec875e5857d8b391eaad4e899f --- /dev/null +++ b/src/lightControlUnit/PresetLed/PresetLed.h @@ -0,0 +1,17 @@ +#ifndef PresetLed_h +#define PresetLed_h +#include <Arduino.h> + +class PresetLed +{ + private: + int redPinOut; + int greenPinOut; + int bluePinOut; + + public: + PresetLed(); + PresetLed(int redPinOut, int greenPinOut, int bluePinOut); + void setColor(bool red, bool green, bool blue); +}; +#endif \ No newline at end of file diff --git a/src/lightControlUnit/PresetRepository/PresetRepository.cpp b/src/lightControlUnit/PresetRepository/PresetRepository.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9577f673364282f74629cc82a218b42bdafaa628 --- /dev/null +++ b/src/lightControlUnit/PresetRepository/PresetRepository.cpp @@ -0,0 +1,171 @@ +#include "PresetRepository.h" +#include "../PresetLed/PresetLed.cpp" +#include "../Preset/Preset.cpp" +#include "../config/config.h" +#include <Arduino.h> + +PresetRepository::PresetRepository(){} + +PresetRepository::PresetRepository(int eepromStartAdress, DmxController* dmxController, int** leds) +{ + this->eepromStartAdress = eepromStartAdress; + this->dmxController = dmxController; + + for(int i = 0; i<NUMBER_OF_PRESETS; i++) + { + this->presets[i] = Preset(eepromStartAdress + (i*sizeof(PresetStoredInfromation)), PresetLed(leds[i][0], leds[i][1], leds[i][2])); + this->presets[i].loadPresetData(); + if(this->presets[i].getState() == P_ACTIVE) { + this->sendDmxValuesOfPreset(i); + } + } +} + +void PresetRepository::sendDmxValuesOfPreset(int presetId) +{ + for(int i = 0; i<MAX_DMX_CHANNEL; i++) + { + if(this->presets[presetId].getDmxChannel()[i].isUsed) + { + this->dmxController->setChannelValue(true, 1+i, this->presets[presetId].getDmxChannel()[i].value); + } + } +} + +void PresetRepository::disableOtherGroupPresets(int presetId) +{ + for(int i = 0; i<NUMBER_OF_PRESETS; i++) { + if((i != presetId) && (this->presets[i].getGroupId() == this->presets[presetId].getGroupId())) + { + this->setPresetDeactiv(i); + } + } +} + +bool PresetRepository::isGroupMemberActive(uint8_t groupId) +{ + bool isActive = false; + for(int i = 0; i < NUMBER_OF_PRESETS; i++) + { + if(this->presets[i].getGroupId() == groupId && this->presets[i].getState() == P_ACTIVE) + { + isActive = true; + } + } + + return isActive; +} + +void PresetRepository::updatePresetState() +{ + for(int i = 0; i < NUMBER_OF_PRESETS; i++) + { + this->presets[i].updateState(this->dmxController->getActiveChannel(), this->isGroupMemberActive(this->presets[i].getGroupId())); + } +} + +void PresetRepository::updatePresetState(uint8_t groupId) +{ + for(int i = 0; i < NUMBER_OF_PRESETS; i++) + { + if(this->presets[i].getGroupId() != groupId) + { + this->presets[i].updateState(this->dmxController->getActiveChannel(), this->isGroupMemberActive(this->presets[i].getGroupId())); + } + } +} + +void PresetRepository::activatePreset(int presetId) +{ + this->setPresetActive(presetId); + this->disableOtherGroupPresets(presetId); + this->sendDmxValuesOfPreset(presetId); + this->updatePresetState(this->presets[presetId].getGroupId()); +} + +void PresetRepository::deactivatePreset(int presetId) +{ + this->setPresetDeactiv(presetId); + for(int i = 0; i<MAX_DMX_CHANNEL; i++) + { + if(this->presets[presetId].getDmxChannel()[i].isUsed) + { + this->dmxController->setChannelValue(false, 1+i, 0); + } + } + this->updatePresetState(this->presets[presetId].getGroupId()); + this->disableOtherGroupPresets(presetId); +} + +void PresetRepository::setPresetActive(int presetId) +{ + this->presets[presetId].setState(P_ACTIVE); + this->presets[presetId].savePresetData(); +} + +void PresetRepository::setPresetDeactiv(int presetId) +{ + this->presets[presetId].setState(P_DEAKTIV); + this->presets[presetId].savePresetData(); +} + +void PresetRepository::activateGroup(uint8_t groupId) +{ + for(int i = 0; i<NUMBER_OF_PRESETS; i++) + { + if(this->presets[i].getGroupId() == groupId) + { + this->presets[i].setState(P_PART_ACTIVE); + this->presets[i].savePresetData(); + } + } +} + +void PresetRepository::deactivateGroup(uint8_t groupId) +{ + for(int i = 0; i<NUMBER_OF_PRESETS; i++) + { + if(this->presets[i].getGroupId() == groupId) + { + this->deactivatePreset(i); + } + } +} + +void PresetRepository::setPresetChannelValue(int presetId, int channel, uint8_t value) +{ + this->presets[presetId].setChannelValue(channel, value); + if(this->presets[presetId].getState() == P_ACTIVE) + { + this->sendDmxValuesOfPreset(presetId); + this->updatePresetState(this->presets[presetId].getGroupId()); + } + this->presets[presetId].savePresetData(); +} + +void PresetRepository::setPresetGroupId(int presetId, uint8_t groupId) +{ + this->presets[presetId].setGroupId(groupId); + this->presets[presetId].savePresetData(); + if(this->presets[presetId].getState() == 1) + { + this->disableOtherGroupPresets(presetId); + } +} + +void PresetRepository::clearPreset(int presetId) +{ + this->deactivatePreset(presetId); + this->presets[presetId].clearPreset(); + this->presets[presetId].savePresetData(); +} + +uint8_t PresetRepository::getPresetState(int presetId) +{ + return this->presets[presetId].getState(); +} + +Preset* PresetRepository::getPresets() +{ + return this->presets; +} \ No newline at end of file diff --git a/src/lightControlUnit/PresetRepository/PresetRepository.h b/src/lightControlUnit/PresetRepository/PresetRepository.h new file mode 100644 index 0000000000000000000000000000000000000000..9301cdf112766c088a0f78803df8145342c771ad --- /dev/null +++ b/src/lightControlUnit/PresetRepository/PresetRepository.h @@ -0,0 +1,34 @@ +#ifndef PresetRepository_h +#define PresetRepository_h + +#include "../Preset/Preset.h" +#include "../DmxController/DmxController.h" + +class PresetRepository +{ + private: + Preset presets[6]; + DmxController* dmxController; + int eepromStartAdress; + void sendDmxValuesOfPreset(int presetId); + void disableOtherGroupPresets(int presetId); + bool isGroupMemberActive(uint8_t groupId); + + public: + PresetRepository(); + PresetRepository(int eepromStartAdress, DmxController* dmxController, int** leds); + void activatePreset(int presetId); + void deactivatePreset(int presetId); + void setPresetActive(int presetId); + void setPresetDeactiv(int presetId); + void activateGroup(uint8_t groupId); + void deactivateGroup(uint8_t groupId); + void setPresetChannelValue(int presetId, int channel, uint8_t value); + void setPresetGroupId(int presetId, uint8_t groupId); + void clearPreset(int presetId); + void updatePresetState(); + void updatePresetState(uint8_t groupId); + uint8_t getPresetState(int presetId); + Preset* getPresets(); +}; +#endif \ No newline at end of file diff --git a/src/lightControlUnit/PresetStoredInfromation/PresetStoredInfromation.h b/src/lightControlUnit/PresetStoredInfromation/PresetStoredInfromation.h new file mode 100644 index 0000000000000000000000000000000000000000..c61019916be65287025d04b7fce95c1f43c18fc8 --- /dev/null +++ b/src/lightControlUnit/PresetStoredInfromation/PresetStoredInfromation.h @@ -0,0 +1,9 @@ +#include "../DmxChannel/DmxChannel.h" + +struct PresetStoredInfromation +{ + public: + uint8_t state; + uint8_t groupId; + DmxChannel dmxChannels[100]; +}; \ No newline at end of file diff --git a/src/lightControlUnit/config/config.h b/src/lightControlUnit/config/config.h new file mode 100644 index 0000000000000000000000000000000000000000..355fd92cd6d31f267ff8ca4326032c42ee791a5d --- /dev/null +++ b/src/lightControlUnit/config/config.h @@ -0,0 +1,68 @@ +// global values +#define MAX_DMX_CHANNEL 100 +#define NUMBER_OF_PRESETS 6 +#define NUMBER_OF_LED_COLORS 3 +#define EEPROM_START_ADRESS 0 +#define PRODUCT_URL "https://gitlab.cvh-server.de/sboettger/kiwi-home-light-control-system/" +#define PRODUCT_URL_LENGTHS 70 + +// Art-Net addresses +#define ART_NET_NET_ADDRESS 0 +#define ART_NET_SUB_NET_ADDRESS 0 +#define ART_NET_UNIVERSE 0 + +// led pins +#define LED_1_PINOUT_R 46 +#define LED_1_PINOUT_G 44 +#define LED_1_PINOUT_B 48 + +#define LED_2_PINOUT_R 40 +#define LED_2_PINOUT_G 38 +#define LED_2_PINOUT_B 42 + +#define LED_3_PINOUT_R 47 +#define LED_3_PINOUT_G 45 +#define LED_3_PINOUT_B 49 + +#define LED_4_PINOUT_R 41 +#define LED_4_PINOUT_G 39 +#define LED_4_PINOUT_B 43 + +#define LED_5_PINOUT_R 35 +#define LED_5_PINOUT_G 33 +#define LED_5_PINOUT_B 37 + +#define LED_6_PINOUT_R 29 +#define LED_6_PINOUT_G 27 +#define LED_6_PINOUT_B 31 + +// buttons pins +#define BUTTON_1_PININ 36 +#define BUTTON_2_PININ 34 +#define BUTTON_3_PININ 32 +#define BUTTON_4_PININ 30 +#define BUTTON_5_PININ 28 +#define BUTTON_6_PININ 26 + +// dmx pins +#define DMX_PINOUT 24 + +// preset state values +#define P_DEAKTIV 0 +#define P_ACTIVE 1 +#define P_PART_ACTIVE 2 + +// common group id values +#define DEFAULT_GROUP_ID 0 + +// ethernet communication +#define MAC_ADDRESS_PART_01 0xA8 +#define MAC_ADDRESS_PART_02 0x61 +#define MAC_ADDRESS_PART_03 0x0A +#define MAC_ADDRESS_PART_04 0xAE +#define MAC_ADDRESS_PART_05 0xE0 +#define MAC_ADDRESS_PART_06 0x13 + +#define UDP_PORT_ADRESS 6454 +#define UPD_MAX_PACKAGE_LENGTH_READ 530 +#define UPD_MAX_PACKAGE_LENGTH_WRITE 532 \ No newline at end of file diff --git a/src/lightControlUnit/lightControlUnit.ino b/src/lightControlUnit/lightControlUnit.ino new file mode 100644 index 0000000000000000000000000000000000000000..6aced8b6955b1758b6dca58ceca6bbbb9852ea11 --- /dev/null +++ b/src/lightControlUnit/lightControlUnit.ino @@ -0,0 +1,125 @@ +// This is the main file of the light controll unit. + +// includes +#include <Arduino.h> +#include <DmxSimple.h> +#include "./config/config.h" +#include "./DmxController/DmxController.cpp" +#include "./PresetRepository/PresetRepository.cpp" +#include "./ArtNetController/ArtNetController.cpp" + + + +// pin values +int led1[] = {LED_1_PINOUT_R, LED_1_PINOUT_G, LED_1_PINOUT_B}; +int led2[] = {LED_2_PINOUT_R, LED_2_PINOUT_G, LED_2_PINOUT_B}; +int led3[] = {LED_3_PINOUT_R, LED_3_PINOUT_G, LED_3_PINOUT_B}; +int led4[] = {LED_4_PINOUT_R, LED_4_PINOUT_G, LED_4_PINOUT_B}; +int led5[] = {LED_5_PINOUT_R, LED_5_PINOUT_G, LED_5_PINOUT_B}; +int led6[] = {LED_6_PINOUT_R, LED_6_PINOUT_G, LED_6_PINOUT_B}; + +int** leds = new int*[NUMBER_OF_PRESETS]; +int buttons[] = {BUTTON_1_PININ, BUTTON_2_PININ, BUTTON_3_PININ, BUTTON_4_PININ, BUTTON_5_PININ, BUTTON_6_PININ}; + +// controller and repositories +DmxController dmxController = DmxController(); +PresetRepository presetRepository; +ArtNetController artNetController; + + + +// setup functions +void setupLedArray() +{ + leds[0] = led1; + leds[1] = led2; + leds[2] = led3; + leds[3] = led4; + leds[4] = led5; + leds[5] = led6; +} + +void setupButtons() +{ + for(int i = 0; i < NUMBER_OF_PRESETS; i++){ + pinMode(buttons[i], INPUT_PULLUP); + } +} + +void setupPresetValues(int presetId, int groupId, int startDmxAdress, uint8_t r, uint8_t g, uint8_t b, uint8_t i, uint8_t f) +{ + presetRepository.setPresetChannelValue(presetId,startDmxAdress,r); + presetRepository.setPresetChannelValue(presetId,1+startDmxAdress,g); + presetRepository.setPresetChannelValue(presetId,2+startDmxAdress,b); + presetRepository.setPresetChannelValue(presetId,3+startDmxAdress,i); + presetRepository.setPresetChannelValue(presetId,4+startDmxAdress,f); + presetRepository.setPresetGroupId(presetId, groupId); +} + +void setupPresetValues() +{ + presetRepository.clearPreset(0); + presetRepository.clearPreset(1); + presetRepository.clearPreset(2); + presetRepository.clearPreset(3); + presetRepository.clearPreset(4); + presetRepository.clearPreset(5); + + setupPresetValues(0,1,1,255,0,0,255,0); // fixture 1 blue + setupPresetValues(0,1,6,255,0,0,255,0); // fixture 2 blue + + setupPresetValues(1,1,1,0,255,0,255,0); // fixture 1 green + setupPresetValues(1,1,6,0,255,0,255,0); // fixture 2 green + + setupPresetValues(2,2,11,255,255,255,100,0); // fixture 3 white + + setupPresetValues(3,3,16,255,0,0,255,0); // fixture 4 red + + setupPresetValues(4,4,1,0,255,0,255,0); // fixture 1 green + setupPresetValues(4,4,6,0,255,0,255,0); // fixture 2 green + setupPresetValues(4,4,11,0,255,0,255,0); // fixture 3 green + setupPresetValues(4,4,16,0,255,0,255,0); // fixture 4 green + + setupPresetValues(5,4,1,255,255,255,255,0); // fixture 1 white + setupPresetValues(5,4,6,255,255,255,255,0); // fixture 2 white + setupPresetValues(5,4,11,255,255,255,255,0); // fixture 3 white + setupPresetValues(5,4,16,255,255,255,255,0); // fixture 4 white + +} + +// check functinos +void checkButtonIsPressed() +{ + for(int i = 0; i < NUMBER_OF_PRESETS; i++) { + if(digitalRead(buttons[i]) == LOW) { + if(presetRepository.getPresetState(i)) + { + presetRepository.deactivatePreset(i); + artNetController.sendPresetDeactivated(i); + } + else + { + presetRepository.activatePreset(i); + artNetController.sendPresetActivated(i); + } + while(digitalRead(buttons[i]) == LOW){} + } + } +} + +void setup() +{ + Serial.begin(250000); + setupLedArray(); + setupButtons(); + + presetRepository = PresetRepository(EEPROM_START_ADRESS, &dmxController, leds); + artNetController = ArtNetController(&dmxController, &presetRepository); + //setupPresetValues(); +} + +void loop() +{ + checkButtonIsPressed(); + artNetController.listenToArtNet(); +}