Added File shard, improved shard icons.
|
@ -1,107 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
width="16"
|
|
||||||
height="16"
|
|
||||||
viewBox="0 0 4.2333333 4.2333333"
|
|
||||||
version="1.1"
|
|
||||||
id="svg8"
|
|
||||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
|
||||||
sodipodi:docname="login_credentials_shard_node_icon.svg"
|
|
||||||
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\login_credentials_shard_node_icon.png"
|
|
||||||
inkscape:export-xdpi="192"
|
|
||||||
inkscape:export-ydpi="192">
|
|
||||||
<defs
|
|
||||||
id="defs2" />
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="base"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:zoom="89.600001"
|
|
||||||
inkscape:cx="10.229603"
|
|
||||||
inkscape:cy="7.4126105"
|
|
||||||
inkscape:document-units="px"
|
|
||||||
inkscape:current-layer="layer1"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1017"
|
|
||||||
inkscape:window-x="-8"
|
|
||||||
inkscape:window-y="-8"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
units="px" />
|
|
||||||
<metadata
|
|
||||||
id="metadata5">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(0,-292.76667)">
|
|
||||||
<path
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="fill:#72deff;fill-opacity:1;stroke:none;stroke-width:0.07803907;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
|
||||||
id="path817"
|
|
||||||
sodipodi:sides="9"
|
|
||||||
sodipodi:cx="2.1166666"
|
|
||||||
sodipodi:cy="294.93815"
|
|
||||||
sodipodi:r1="1.8178079"
|
|
||||||
sodipodi:r2="1.2179312"
|
|
||||||
sodipodi:arg1="0.52359878"
|
|
||||||
sodipodi:arg2="0.87266463"
|
|
||||||
inkscape:flatsided="false"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="m 3.6909344,295.84704 -0.7913968,0.0241 -0.1611441,0.77519 -0.6217269,-0.49025 -0.621727,0.49025 -0.1611441,-0.77519 -0.79139678,-0.0241 0.37483979,-0.69741 -0.59076328,-0.52715 0.73543197,-0.2933 -0.11370504,-0.78356 0.75190744,0.24804 0.416557,-0.67333 0.4165569,0.67333 0.7519075,-0.24804 -0.1137051,0.78356 0.735432,0.2933 -0.5907633,0.52715 z"
|
|
||||||
inkscape:transform-center-x="0.06028767"
|
|
||||||
inkscape:transform-center-y="0.030212626" />
|
|
||||||
<g
|
|
||||||
id="g828">
|
|
||||||
<rect
|
|
||||||
y="294.87439"
|
|
||||||
x="1.5420023"
|
|
||||||
height="0.95215333"
|
|
||||||
width="1.1493286"
|
|
||||||
id="rect816"
|
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.05291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />
|
|
||||||
<path
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
id="path818"
|
|
||||||
d="m 1.8074821,294.89943 v -0.43431 c 0,0 -0.016704,-0.32365 0.3236467,-0.32365 0.340351,0 0.292326,0.29233 0.292326,0.29233 v 0.47816"
|
|
||||||
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
|
||||||
<rect
|
|
||||||
y="295.05811"
|
|
||||||
x="1.7157624"
|
|
||||||
height="0.17957026"
|
|
||||||
width="0.8018086"
|
|
||||||
id="rect820"
|
|
||||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.05291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />
|
|
||||||
<rect
|
|
||||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.05291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
|
||||||
id="rect822"
|
|
||||||
width="0.8018086"
|
|
||||||
height="0.17957026"
|
|
||||||
x="1.7157624"
|
|
||||||
y="295.41309" />
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.4 KiB |
|
@ -16,9 +16,9 @@
|
||||||
id="svg8"
|
id="svg8"
|
||||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
sodipodi:docname="shard_node_icon.svg"
|
sodipodi:docname="shard_node_icon.svg"
|
||||||
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\ui\images\shard_node_icon.png"
|
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\shard_node_icon.png"
|
||||||
inkscape:export-xdpi="192"
|
inkscape:export-xdpi="1536"
|
||||||
inkscape:export-ydpi="192">
|
inkscape:export-ydpi="1536">
|
||||||
<defs
|
<defs
|
||||||
id="defs2" />
|
id="defs2" />
|
||||||
<sodipodi:namedview
|
<sodipodi:namedview
|
||||||
|
@ -28,9 +28,9 @@
|
||||||
borderopacity="1.0"
|
borderopacity="1.0"
|
||||||
inkscape:pageopacity="0.0"
|
inkscape:pageopacity="0.0"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="31.678384"
|
inkscape:zoom="44.8"
|
||||||
inkscape:cx="4.3963569"
|
inkscape:cx="8.5805581"
|
||||||
inkscape:cy="7.5940447"
|
inkscape:cy="7.3490264"
|
||||||
inkscape:document-units="px"
|
inkscape:document-units="px"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
showgrid="false"
|
showgrid="false"
|
||||||
|
@ -39,7 +39,9 @@
|
||||||
inkscape:window-x="-8"
|
inkscape:window-x="-8"
|
||||||
inkscape:window-y="-8"
|
inkscape:window-y="-8"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1"
|
||||||
units="px" />
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true" />
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata5">
|
id="metadata5">
|
||||||
<rdf:RDF>
|
<rdf:RDF>
|
||||||
|
@ -58,21 +60,9 @@
|
||||||
id="layer1"
|
id="layer1"
|
||||||
transform="translate(0,-292.76667)">
|
transform="translate(0,-292.76667)">
|
||||||
<path
|
<path
|
||||||
sodipodi:type="star"
|
style="fill:#00f8c5;stroke:none;stroke-width:0.26458333;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1"
|
||||||
style="fill:#72deff;fill-opacity:1;stroke:none;stroke-width:0.07803907;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
d="m 2.1143043,292.83045 1.1824699,2.0481 -1.1824699,2.0481 -1.18246994,-2.0481 1.18246994,-2.0481"
|
||||||
id="path817"
|
id="path820"
|
||||||
sodipodi:sides="9"
|
inkscape:connector-curvature="0" />
|
||||||
sodipodi:cx="2.1166666"
|
|
||||||
sodipodi:cy="294.93815"
|
|
||||||
sodipodi:r1="1.8178079"
|
|
||||||
sodipodi:r2="1.2179312"
|
|
||||||
sodipodi:arg1="0.52359878"
|
|
||||||
sodipodi:arg2="0.87266463"
|
|
||||||
inkscape:flatsided="false"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="m 3.6909344,295.84704 -0.7913968,0.0241 -0.1611441,0.77519 -0.6217269,-0.49025 -0.621727,0.49025 -0.1611441,-0.77519 -0.79139678,-0.0241 0.37483979,-0.69741 -0.59076328,-0.52715 0.73543197,-0.2933 -0.11370504,-0.78356 0.75190744,0.24804 0.416557,-0.67333 0.4165569,0.67333 0.7519075,-0.24804 -0.1137051,0.78356 0.735432,0.2933 -0.5907633,0.52715 z"
|
|
||||||
inkscape:transform-center-x="0.06028767"
|
|
||||||
inkscape:transform-center-y="0.030212626" />
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,78 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 4.2333333 4.2333333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="file.svg"
|
||||||
|
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\file_shard_node_icon.png"
|
||||||
|
inkscape:export-xdpi="1536"
|
||||||
|
inkscape:export-ydpi="1536">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="32"
|
||||||
|
inkscape:cx="10.333173"
|
||||||
|
inkscape:cy="9.4475152"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-292.76667)">
|
||||||
|
<g
|
||||||
|
id="g832"
|
||||||
|
transform="matrix(2.2606665,0,0,2.2606665,-2.7169913,-371.69624)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path826"
|
||||||
|
d="m 2.4538923,294.00575 v 0.19782 H 2.664343 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.01322917;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path824"
|
||||||
|
d="m 1.6119693,295.71377 v -1.70802 h 0.841923 v 0.19782 H 2.664343 v 1.5102 z"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.02645833;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,95 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="16"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 4.2333333 4.2333333"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="login_credentials.svg"
|
||||||
|
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\login_credentials_shard_node_icon.png"
|
||||||
|
inkscape:export-xdpi="1536"
|
||||||
|
inkscape:export-ydpi="1536">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="45.254834"
|
||||||
|
inkscape:cx="12.226157"
|
||||||
|
inkscape:cy="8.1661844"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1017"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:lockguides="true">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0.52618688,3.2974378"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide815"
|
||||||
|
inkscape:locked="true" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="1.0348342,3.7066942"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide817"
|
||||||
|
inkscape:locked="true" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="3.7008477,2.8238696"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide819"
|
||||||
|
inkscape:locked="true" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="-0.59634513,0.5320334"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide821"
|
||||||
|
inkscape:locked="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-292.76667)">
|
||||||
|
<path
|
||||||
|
style="fill:#edf9fd;stroke:#000000;stroke-width:0.396875;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1"
|
||||||
|
d="m 0.52618687,294.18783 v -0.89452 H 3.7008477 v 3.17466 H 0.52618687 v -1.07576"
|
||||||
|
id="path823"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.396875;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
d="M 0.22324218,294.76758 H 2.5879557 l -0.72347,-0.72347 0.72347,0.72347 -0.7420736,0.74207"
|
||||||
|
id="path825"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
|
@ -15,10 +15,10 @@
|
||||||
version="1.1"
|
version="1.1"
|
||||||
id="svg8"
|
id="svg8"
|
||||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
sodipodi:docname="text_shard_node_icon.svg"
|
sodipodi:docname="text.svg"
|
||||||
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\text_shard_node_icon.png"
|
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\text_shard_node_icon.png"
|
||||||
inkscape:export-xdpi="192"
|
inkscape:export-xdpi="1536"
|
||||||
inkscape:export-ydpi="192">
|
inkscape:export-ydpi="1536">
|
||||||
<defs
|
<defs
|
||||||
id="defs2" />
|
id="defs2" />
|
||||||
<sodipodi:namedview
|
<sodipodi:namedview
|
||||||
|
@ -29,8 +29,8 @@
|
||||||
inkscape:pageopacity="0.0"
|
inkscape:pageopacity="0.0"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:zoom="44.8"
|
inkscape:zoom="44.8"
|
||||||
inkscape:cx="8.2633984"
|
inkscape:cx="5.8060872"
|
||||||
inkscape:cy="6.8552682"
|
inkscape:cy="8.9176258"
|
||||||
inkscape:document-units="px"
|
inkscape:document-units="px"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
showgrid="false"
|
showgrid="false"
|
||||||
|
@ -39,7 +39,9 @@
|
||||||
inkscape:window-x="-8"
|
inkscape:window-x="-8"
|
||||||
inkscape:window-y="-8"
|
inkscape:window-y="-8"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1"
|
||||||
units="px" />
|
units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true" />
|
||||||
<metadata
|
<metadata
|
||||||
id="metadata5">
|
id="metadata5">
|
||||||
<rdf:RDF>
|
<rdf:RDF>
|
||||||
|
@ -57,33 +59,16 @@
|
||||||
inkscape:groupmode="layer"
|
inkscape:groupmode="layer"
|
||||||
id="layer1"
|
id="layer1"
|
||||||
transform="translate(0,-292.76667)">
|
transform="translate(0,-292.76667)">
|
||||||
<path
|
|
||||||
sodipodi:type="star"
|
|
||||||
style="fill:#72deff;fill-opacity:1;stroke:none;stroke-width:0.07803907;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
|
||||||
id="path817"
|
|
||||||
sodipodi:sides="9"
|
|
||||||
sodipodi:cx="2.1166666"
|
|
||||||
sodipodi:cy="294.93815"
|
|
||||||
sodipodi:r1="1.8178079"
|
|
||||||
sodipodi:r2="1.2179312"
|
|
||||||
sodipodi:arg1="0.52359878"
|
|
||||||
sodipodi:arg2="0.87266463"
|
|
||||||
inkscape:flatsided="false"
|
|
||||||
inkscape:rounded="0"
|
|
||||||
inkscape:randomized="0"
|
|
||||||
d="m 3.6909344,295.84704 -0.7913968,0.0241 -0.1611441,0.77519 -0.6217269,-0.49025 -0.621727,0.49025 -0.1611441,-0.77519 -0.79139678,-0.0241 0.37483979,-0.69741 -0.59076328,-0.52715 0.73543197,-0.2933 -0.11370504,-0.78356 0.75190744,0.24804 0.416557,-0.67333 0.4165569,0.67333 0.7519075,-0.24804 -0.1137051,0.78356 0.735432,0.2933 -0.5907633,0.52715 z"
|
|
||||||
inkscape:transform-center-x="0.06028767"
|
|
||||||
inkscape:transform-center-y="0.030212626" />
|
|
||||||
<text
|
<text
|
||||||
xml:space="preserve"
|
xml:space="preserve"
|
||||||
style="font-style:normal;font-weight:normal;font-size:1.9992249px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.12495156"
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.69617891px;line-height:1.25;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35601118"
|
||||||
x="1.4333378"
|
x="0.36164278"
|
||||||
y="295.61206"
|
y="296.76907"
|
||||||
id="text818"><tspan
|
id="text817"><tspan
|
||||||
sodipodi:role="line"
|
sodipodi:role="line"
|
||||||
id="tspan816"
|
id="tspan815"
|
||||||
x="1.4333378"
|
x="0.36164278"
|
||||||
y="295.61206"
|
y="296.76907"
|
||||||
style="stroke-width:0.12495156">A</tspan></text>
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.69617891px;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.35601118">T</tspan></text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.0 KiB |
|
@ -53,7 +53,7 @@ public class AddShardHandler implements EventHandler<ActionEvent> {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TEXT: return new TextShard(name);
|
case TEXT: return new TextShard(name);
|
||||||
case LOGIN_CREDENTIALS: return new LoginCredentialsShard(name);
|
case LOGIN_CREDENTIALS: return new LoginCredentialsShard(name);
|
||||||
case FILE: return new FileShard(name, "", "", new byte[0]);
|
case FILE: return new FileShard(name, "", new byte[0]);
|
||||||
default: return null;
|
default: return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import javafx.scene.control.TreeItem;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import nl.andrewlalis.crystalkeep.model.CrystalItem;
|
import nl.andrewlalis.crystalkeep.model.CrystalItem;
|
||||||
import nl.andrewlalis.crystalkeep.view.ShardTreeItem;
|
import nl.andrewlalis.crystalkeep.view.ShardTreeItem;
|
||||||
import nl.andrewlalis.crystalkeep.view.shard_details.ViewModels;
|
import nl.andrewlalis.crystalkeep.view.shards.ViewModels;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This listener will update the shard detail container pane (the main center
|
* This listener will update the shard detail container pane (the main center
|
||||||
|
|
|
@ -23,6 +23,8 @@ public class MainViewController implements ModelListener {
|
||||||
public TreeView<CrystalItem> clusterTreeView;
|
public TreeView<CrystalItem> clusterTreeView;
|
||||||
@FXML
|
@FXML
|
||||||
public VBox shardDetailContainer;
|
public VBox shardDetailContainer;
|
||||||
|
@FXML
|
||||||
|
public Menu fileMenu;
|
||||||
|
|
||||||
public void init(Model model) {
|
public void init(Model model) {
|
||||||
this.model = model;
|
this.model = model;
|
||||||
|
@ -91,7 +93,6 @@ public class MainViewController implements ModelListener {
|
||||||
@FXML
|
@FXML
|
||||||
public void save() {
|
public void save() {
|
||||||
if (model.getActiveCluster() == null) return;
|
if (model.getActiveCluster() == null) return;
|
||||||
ClusterIO loader = new ClusterIO();
|
|
||||||
Path path = model.getActiveClusterPath();
|
Path path = model.getActiveClusterPath();
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
FileChooser chooser = new FileChooser();
|
FileChooser chooser = new FileChooser();
|
||||||
|
@ -102,27 +103,12 @@ public class MainViewController implements ModelListener {
|
||||||
if (file == null) return;
|
if (file == null) return;
|
||||||
path = file.toPath();
|
path = file.toPath();
|
||||||
}
|
}
|
||||||
char[] pw = this.model.getActiveClusterPassword();
|
this.saveCluster(path);
|
||||||
if (pw == null) {
|
|
||||||
pw = this.promptPassword().orElse(new char[0]);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (pw.length == 0) {
|
|
||||||
loader.saveUnencrypted(model.getActiveCluster(), path);
|
|
||||||
} else {
|
|
||||||
loader.save(model.getActiveCluster(), path, pw);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
var alert = new Alert(Alert.AlertType.ERROR, "Could not save cluster.");
|
|
||||||
alert.showAndWait();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void saveAs() {
|
public void saveAs() {
|
||||||
if (model.getActiveCluster() == null) return;
|
if (model.getActiveCluster() == null) return;
|
||||||
ClusterIO clusterIO = new ClusterIO();
|
|
||||||
Path path = model.getActiveClusterPath();
|
Path path = model.getActiveClusterPath();
|
||||||
FileChooser chooser = new FileChooser();
|
FileChooser chooser = new FileChooser();
|
||||||
chooser.setTitle("Save Cluster");
|
chooser.setTitle("Save Cluster");
|
||||||
|
@ -133,21 +119,7 @@ public class MainViewController implements ModelListener {
|
||||||
File file = chooser.showSaveDialog(this.clusterTreeView.getScene().getWindow());
|
File file = chooser.showSaveDialog(this.clusterTreeView.getScene().getWindow());
|
||||||
if (file == null) return;
|
if (file == null) return;
|
||||||
path = file.toPath();
|
path = file.toPath();
|
||||||
char[] pw = this.model.getActiveClusterPassword();
|
this.saveCluster(path);
|
||||||
if (pw == null) {
|
|
||||||
pw = this.promptPassword().orElse(new char[0]);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (pw.length == 0) {
|
|
||||||
clusterIO.saveUnencrypted(model.getActiveCluster(), path);
|
|
||||||
} else {
|
|
||||||
clusterIO.save(model.getActiveCluster(), path, pw);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
var alert = new Alert(Alert.AlertType.ERROR, "Could not save cluster.");
|
|
||||||
alert.showAndWait();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -175,4 +147,23 @@ public class MainViewController implements ModelListener {
|
||||||
});
|
});
|
||||||
return d.showAndWait();
|
return d.showAndWait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void saveCluster(Path path) {
|
||||||
|
char[] pw = this.model.getActiveClusterPassword();
|
||||||
|
if (pw == null) {
|
||||||
|
pw = this.promptPassword().orElse(new char[0]);
|
||||||
|
}
|
||||||
|
ClusterIO loader = new ClusterIO();
|
||||||
|
try {
|
||||||
|
if (pw.length == 0) {
|
||||||
|
loader.saveUnencrypted(model.getActiveCluster(), path);
|
||||||
|
} else {
|
||||||
|
loader.save(model.getActiveCluster(), path, pw);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
var alert = new Alert(Alert.AlertType.ERROR, "Could not save cluster.");
|
||||||
|
alert.showAndWait();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package nl.andrewlalis.crystalkeep.io.serialization;
|
package nl.andrewlalis.crystalkeep.io.serialization;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -25,6 +24,32 @@ public class ByteUtils {
|
||||||
os.write(toBytes(value));
|
os.write(toBytes(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] longToBytes(long l) {
|
||||||
|
byte[] result = new byte[8];
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
result[i] = (byte)(l & 0xFF);
|
||||||
|
l >>= 8;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long bytesToLong(final byte[] b) {
|
||||||
|
long result = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
result <<= 8;
|
||||||
|
result |= (b[i] & 0xFF);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeLong(long value, OutputStream os) throws IOException {
|
||||||
|
os.write(longToBytes(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long readLong(InputStream is) throws IOException {
|
||||||
|
return bytesToLong(is.readNBytes(Long.BYTES));
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeLengthPrefixed(byte[] bytes, OutputStream os) throws IOException {
|
public static void writeLengthPrefixed(byte[] bytes, OutputStream os) throws IOException {
|
||||||
os.write(toBytes(bytes.length));
|
os.write(toBytes(bytes.length));
|
||||||
os.write(bytes);
|
os.write(bytes);
|
||||||
|
@ -34,12 +59,10 @@ public class ByteUtils {
|
||||||
writeLengthPrefixed(s.getBytes(StandardCharsets.UTF_8), os);
|
writeLengthPrefixed(s.getBytes(StandardCharsets.UTF_8), os);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] writeLengthPrefixedStrings(String[] strings) throws IOException {
|
public static void writeLengthPrefixedStrings(String[] strings, OutputStream os) throws IOException {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
for (String s : strings) {
|
for (String s : strings) {
|
||||||
writeLengthPrefixed(s, bos);
|
writeLengthPrefixed(s, os);
|
||||||
}
|
}
|
||||||
return bos.toByteArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] readLengthPrefixed(InputStream is) throws IOException {
|
public static byte[] readLengthPrefixed(InputStream is) throws IOException {
|
||||||
|
|
|
@ -2,8 +2,9 @@ package nl.andrewlalis.crystalkeep.io.serialization;
|
||||||
|
|
||||||
import nl.andrewlalis.crystalkeep.model.Cluster;
|
import nl.andrewlalis.crystalkeep.model.Cluster;
|
||||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
|
||||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.shards.FileShard;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
||||||
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -27,6 +28,7 @@ public class ClusterSerializer {
|
||||||
static {
|
static {
|
||||||
serializers.put(ShardType.TEXT, new TextShard.Serializer());
|
serializers.put(ShardType.TEXT, new TextShard.Serializer());
|
||||||
serializers.put(ShardType.LOGIN_CREDENTIALS, new LoginCredentialsShard.Serializer());
|
serializers.put(ShardType.LOGIN_CREDENTIALS, new LoginCredentialsShard.Serializer());
|
||||||
|
serializers.put(ShardType.FILE, new FileShard.Serializer());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,7 +84,7 @@ public class ClusterSerializer {
|
||||||
ByteUtils.writeLengthPrefixed(shard.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).getBytes(StandardCharsets.UTF_8), os);
|
ByteUtils.writeLengthPrefixed(shard.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).getBytes(StandardCharsets.UTF_8), os);
|
||||||
os.write(ByteUtils.toBytes(shard.getType().getValue()));
|
os.write(ByteUtils.toBytes(shard.getType().getValue()));
|
||||||
ShardSerializer serializer = serializers.get(shard.getType());
|
ShardSerializer serializer = serializers.get(shard.getType());
|
||||||
os.write(serializer.serialize(shard));
|
serializer.serialize(shard, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,10 +4,16 @@ import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface should be implemented to provide the ability to serialize and
|
||||||
|
* deserialize a shard to and from a stream of bytes.
|
||||||
|
* @param <T> The shard type.
|
||||||
|
*/
|
||||||
public interface ShardSerializer<T extends Shard> {
|
public interface ShardSerializer<T extends Shard> {
|
||||||
byte[] serialize(T shard) throws IOException;
|
void serialize(T shard, OutputStream os) throws IOException;
|
||||||
|
|
||||||
T deserialize(InputStream is, String name, LocalDateTime createdAt) throws IOException;
|
T deserialize(InputStream is, String name, LocalDateTime createdAt) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,57 @@
|
||||||
package nl.andrewlalis.crystalkeep.model.shards;
|
package nl.andrewlalis.crystalkeep.model.shards;
|
||||||
|
|
||||||
|
import nl.andrewlalis.crystalkeep.io.serialization.ByteUtils;
|
||||||
|
import nl.andrewlalis.crystalkeep.io.serialization.ShardSerializer;
|
||||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class FileShard extends Shard {
|
public class FileShard extends Shard {
|
||||||
private String fileName;
|
private String fileName;
|
||||||
private String mimeType;
|
|
||||||
private byte[] contents;
|
private byte[] contents;
|
||||||
|
|
||||||
public FileShard(String name, LocalDateTime createdAt, String fileName, String mimeType, byte[] contents) {
|
public FileShard(String name, LocalDateTime createdAt, String fileName, byte[] contents) {
|
||||||
super(name, createdAt, ShardType.FILE);
|
super(name, createdAt, ShardType.FILE);
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
this.mimeType = mimeType;
|
|
||||||
this.contents = contents;
|
this.contents = contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileShard(String name, String fileName, String mimeType, byte[] contents) {
|
public FileShard(String name, String fileName, byte[] contents) {
|
||||||
this(name, LocalDateTime.now(), fileName, mimeType, contents);
|
this(name, LocalDateTime.now(), fileName, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFileName() {
|
public String getFileName() {
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMimeType() {
|
public void setFileName(String fileName) {
|
||||||
return mimeType;
|
this.fileName = fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getContents() {
|
public byte[] getContents() {
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContents(byte[] contents) {
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Serializer implements ShardSerializer<FileShard> {
|
||||||
|
@Override
|
||||||
|
public void serialize(FileShard shard, OutputStream os) throws IOException {
|
||||||
|
ByteUtils.writeLengthPrefixed(shard.getFileName(), os);
|
||||||
|
ByteUtils.writeLengthPrefixed(shard.getContents(), os);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileShard deserialize(InputStream is, String name, LocalDateTime createdAt) throws IOException {
|
||||||
|
String fileName = ByteUtils.readLengthPrefixedString(is);
|
||||||
|
byte[] contents = ByteUtils.readLengthPrefixed(is);
|
||||||
|
return new FileShard(name, createdAt, fileName, contents);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package nl.andrewlalis.crystalkeep.model.shards;
|
package nl.andrewlalis.crystalkeep.model.shards;
|
||||||
|
|
||||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
|
||||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
|
||||||
import nl.andrewlalis.crystalkeep.io.serialization.ByteUtils;
|
import nl.andrewlalis.crystalkeep.io.serialization.ByteUtils;
|
||||||
import nl.andrewlalis.crystalkeep.io.serialization.ShardSerializer;
|
import nl.andrewlalis.crystalkeep.io.serialization.ShardSerializer;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class LoginCredentialsShard extends Shard {
|
public class LoginCredentialsShard extends Shard {
|
||||||
|
@ -44,11 +45,11 @@ public class LoginCredentialsShard extends Shard {
|
||||||
return super.toString() + ", username=\"" + this.username + "\", password=\"" + this.password + "\"";
|
return super.toString() + ", username=\"" + this.username + "\", password=\"" + this.password + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements ShardSerializer<LoginCredentialsShard> {
|
public static final class Serializer implements ShardSerializer<LoginCredentialsShard> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(LoginCredentialsShard shard) throws IOException {
|
public void serialize(LoginCredentialsShard shard, OutputStream os) throws IOException {
|
||||||
return ByteUtils.writeLengthPrefixedStrings(new String[]{shard.getUsername(), shard.getPassword()});
|
ByteUtils.writeLengthPrefixedStrings(new String[]{shard.getUsername(), shard.getPassword()}, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package nl.andrewlalis.crystalkeep.model.shards;
|
package nl.andrewlalis.crystalkeep.model.shards;
|
||||||
|
|
||||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
|
||||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
|
||||||
import nl.andrewlalis.crystalkeep.io.serialization.ByteUtils;
|
import nl.andrewlalis.crystalkeep.io.serialization.ByteUtils;
|
||||||
import nl.andrewlalis.crystalkeep.io.serialization.ShardSerializer;
|
import nl.andrewlalis.crystalkeep.io.serialization.ShardSerializer;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class TextShard extends Shard {
|
public class TextShard extends Shard {
|
||||||
|
@ -34,10 +35,10 @@ public class TextShard extends Shard {
|
||||||
return super.toString() + ", text=\"" + this.text + "\"";
|
return super.toString() + ", text=\"" + this.text + "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements ShardSerializer<TextShard> {
|
public static final class Serializer implements ShardSerializer<TextShard> {
|
||||||
@Override
|
@Override
|
||||||
public byte[] serialize(TextShard shard) throws IOException {
|
public void serialize(TextShard shard, OutputStream os) throws IOException {
|
||||||
return ByteUtils.writeLengthPrefixedStrings(new String[]{shard.getText()});
|
ByteUtils.writeLengthPrefixedStrings(new String[]{shard.getText()}, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package nl.andrewlalis.crystalkeep.util;
|
||||||
|
|
||||||
|
public class StringUtils {
|
||||||
|
public static boolean endsWithAny(String s, String... suffixes) {
|
||||||
|
for (String suffix : suffixes) {
|
||||||
|
if (s.endsWith(suffix)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,7 @@ import nl.andrewlalis.crystalkeep.model.CrystalItem;
|
||||||
import nl.andrewlalis.crystalkeep.model.Model;
|
import nl.andrewlalis.crystalkeep.model.Model;
|
||||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
import nl.andrewlalis.crystalkeep.util.ImageCache;
|
import nl.andrewlalis.crystalkeep.util.ImageCache;
|
||||||
import nl.andrewlalis.crystalkeep.view.shard_details.ViewModels;
|
import nl.andrewlalis.crystalkeep.view.shards.ViewModels;
|
||||||
|
|
||||||
public class CrystalItemTreeCell extends TreeCell<CrystalItem> {
|
public class CrystalItemTreeCell extends TreeCell<CrystalItem> {
|
||||||
private static final String CLUSTER_ICON = "/nl/andrewlalis/crystalkeep/ui/images/cluster_node_icon.png";
|
private static final String CLUSTER_ICON = "/nl/andrewlalis/crystalkeep/ui/images/cluster_node_icon.png";
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
package nl.andrewlalis.crystalkeep.view.shards;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Orientation;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.shards.FileShard;
|
||||||
|
import nl.andrewlalis.crystalkeep.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class FileShardViewModel extends ShardViewModel<FileShard> {
|
||||||
|
public FileShardViewModel(FileShard shard) {
|
||||||
|
super(shard);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Node getContent(FileShard shard) {
|
||||||
|
VBox container = new VBox(10);
|
||||||
|
container.setPadding(new Insets(5));
|
||||||
|
GridPane gp = new GridPane();
|
||||||
|
gp.setVgap(5);
|
||||||
|
gp.setHgap(5);
|
||||||
|
|
||||||
|
gp.add(new Label("File Name"), 0, 0);
|
||||||
|
TextField nameField = new TextField(shard.getFileName());
|
||||||
|
nameField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
shard.setFileName(newValue);
|
||||||
|
});
|
||||||
|
gp.add(nameField, 1, 0);
|
||||||
|
gp.add(new Label("File Size"), 0, 1);
|
||||||
|
TextField sizeField = new TextField(shard.getContents().length + " bytes");
|
||||||
|
sizeField.setEditable(false);
|
||||||
|
gp.add(sizeField, 1, 1);
|
||||||
|
|
||||||
|
Button setFileButton = new Button("Set File");
|
||||||
|
setFileButton.setOnAction(event -> {
|
||||||
|
FileChooser chooser = new FileChooser();
|
||||||
|
chooser.setTitle("Choose a File");
|
||||||
|
File file = chooser.showOpenDialog(gp.getScene().getWindow());
|
||||||
|
if (file != null) {
|
||||||
|
try (FileInputStream fis = new FileInputStream(file)) {
|
||||||
|
byte[] contents = fis.readAllBytes();
|
||||||
|
shard.setFileName(file.getName());
|
||||||
|
shard.setContents(contents);
|
||||||
|
nameField.setText(shard.getFileName());
|
||||||
|
sizeField.setText(shard.getContents().length + " bytes");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gp.add(setFileButton, 0, 2);
|
||||||
|
|
||||||
|
Button extractFileButton = new Button("Extract File");
|
||||||
|
extractFileButton.setOnAction(event -> {
|
||||||
|
FileChooser chooser = new FileChooser();
|
||||||
|
chooser.setTitle("Extract File");
|
||||||
|
chooser.setInitialFileName(shard.getFileName());
|
||||||
|
File file = chooser.showSaveDialog(gp.getScene().getWindow());
|
||||||
|
if (file != null) {
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(file)) {
|
||||||
|
fos.write(shard.getContents());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
gp.add(extractFileButton, 1, 2);
|
||||||
|
container.getChildren().add(gp);
|
||||||
|
|
||||||
|
if (StringUtils.endsWithAny(shard.getFileName().toLowerCase(), ".png", ".jpg", ".jpeg", ".gif")) {
|
||||||
|
container.getChildren().add(new Separator(Orientation.HORIZONTAL));
|
||||||
|
ImageView imageView = new ImageView(new Image(new ByteArrayInputStream(shard.getContents())));
|
||||||
|
imageView.setPreserveRatio(true);
|
||||||
|
ScrollPane scrollPane = new ScrollPane(imageView);
|
||||||
|
container.getChildren().add(scrollPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIconPath() {
|
||||||
|
return "/nl/andrewlalis/crystalkeep/ui/images/file_shard_node_icon.png";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
package nl.andrewlalis.crystalkeep.view.shards;
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
package nl.andrewlalis.crystalkeep.view.shards;
|
||||||
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
|
@ -1,4 +1,4 @@
|
||||||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
package nl.andrewlalis.crystalkeep.view.shards;
|
||||||
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.TextArea;
|
import javafx.scene.control.TextArea;
|
|
@ -1,6 +1,7 @@
|
||||||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
package nl.andrewlalis.crystalkeep.view.shards;
|
||||||
|
|
||||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||||
|
import nl.andrewlalis.crystalkeep.model.shards.FileShard;
|
||||||
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
||||||
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ public class ViewModels {
|
||||||
static {
|
static {
|
||||||
shardViewModels.put(TextShard.class, TextShardViewModel.class);
|
shardViewModels.put(TextShard.class, TextShardViewModel.class);
|
||||||
shardViewModels.put(LoginCredentialsShard.class, LoginCredentialsViewModel.class);
|
shardViewModels.put(LoginCredentialsShard.class, LoginCredentialsViewModel.class);
|
||||||
|
shardViewModels.put(FileShard.class, FileShardViewModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<ShardViewModel<?>> get(Shard shard) {
|
public static Optional<ShardViewModel<?>> get(Shard shard) {
|
|
@ -4,7 +4,7 @@
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.andrewlalis.crystalkeep.control.MainViewController">
|
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="nl.andrewlalis.crystalkeep.control.MainViewController">
|
||||||
<MenuBar>
|
<MenuBar>
|
||||||
<Menu text="File">
|
<Menu fx:id="fileMenu" text="File">
|
||||||
<MenuItem text="New" onAction="#newCluster" />
|
<MenuItem text="New" onAction="#newCluster" />
|
||||||
<MenuItem text="Load" onAction="#load" />
|
<MenuItem text="Load" onAction="#load" />
|
||||||
<MenuItem text="Save" onAction="#save" />
|
<MenuItem text="Save" onAction="#save" />
|
||||||
|
|
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.3 KiB |