diff --git a/app/assets/css-files.yml b/app/assets/css-files.yml index 4d934646..cb4c1d31 100644 --- a/app/assets/css-files.yml +++ b/app/assets/css-files.yml @@ -1,15 +1,15 @@ # Copyright (C) 2012 Matsukei Co.,Ltd. -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . @@ -43,3 +43,4 @@ - toolbox.css - view.css - workspace.css +- fontvalidator.css diff --git a/app/assets/fontoption.css b/app/assets/fontoption.css index 10586bb5..13619fe8 100644 --- a/app/assets/fontoption.css +++ b/app/assets/fontoption.css @@ -37,6 +37,13 @@ box-sizing: border-box; } +.thin-font-option-invalid .thin-font-option-content { + background-image: url(icons/exclamation-octagon.png); + background-position: 0% 50%; + background-repeat: no-repeat; + padding-left: 18px; +} + /* * FontOptionMenu */ diff --git a/app/assets/fontvalidator.css b/app/assets/fontvalidator.css new file mode 100644 index 00000000..0ce07dd6 --- /dev/null +++ b/app/assets/fontvalidator.css @@ -0,0 +1,15 @@ +@font-face { + font-family: AdobeBlank; + src: + url("data:font/opentype;base64,T1RUTwAKAIAAAwAgQ0ZGIDTeCDQAACFkAAAZPERTSUcAAAABAABKqAAAAAhPUy8yAF+xmwAAARAAAABgY21hcCRDbtEAAAdcAAAZ6GhlYWQFl9tDAAAArAAAADZoaGVhB1oD7wAAAOQAAAAkaG10eAPoAHwAADqgAAAQBm1heHAIAVAAAAABCAAAAAZuYW1lIE0HkgAAAXAAAAXrcG9zdP+4ADIAACFEAAAAIAABAAAAAQuFfcPHtV8PPPUAAwPoAAAAANFMRfMAAAAA0UxF8wB8/4gDbANwAAAAAwACAAAAAAAAAAEAAANw/4gAAAPoAHwAfANsAAEAAAAAAAAAAAAAAAAAAAACAABQAAgBAAAAAwPoAZAABQAAAooCWAAAAEsCigJYAAABXgAyANwAAAAAAAAAAAAAAAD3/67/+9///w/gAD8AAAAAQURCTwBAAAD//wNw/4gAAANwAHhgLwH/AAAAAAAAAAAAAAAgAAAAAAARANIAAQAAAAAAAQALAAAAAQAAAAAAAgAHAAsAAQAAAAAAAwAbABIAAQAAAAAABAALAAAAAQAAAAAABQA6AC0AAQAAAAAABgAKAGcAAwABBAkAAACUAHEAAwABBAkAAQAWAQUAAwABBAkAAgAOARsAAwABBAkAAwA2ASkAAwABBAkABAAWAQUAAwABBAkABQB0AV8AAwABBAkABgAUAdMAAwABBAkACAA0AecAAwABBAkACwA0AhsAAwABBAkADQKWAk8AAwABBAkADgA0BOVBZG9iZSBCbGFua1JlZ3VsYXIxLjA0NTtBREJPO0Fkb2JlQmxhbms7QURPQkVWZXJzaW9uIDEuMDQ1O1BTIDEuMDQ1O2hvdGNvbnYgMS4wLjgyO21ha2VvdGYubGliMi41LjYzNDA2QWRvYmVCbGFuawBDAG8AcAB5AHIAaQBnAGgAdAAgAKkAIAAyADAAMQAzACwAIAAyADAAMQA1ACAAQQBkAG8AYgBlACAAUwB5AHMAdABlAG0AcwAgAEkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAAKABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwApAC4AQQBkAG8AYgBlACAAQgBsAGEAbgBrAFIAZQBnAHUAbABhAHIAMQAuADAANAA1ADsAQQBEAEIATwA7AEEAZABvAGIAZQBCAGwAYQBuAGsAOwBBAEQATwBCAEUAVgBlAHIAcwBpAG8AbgAgADEALgAwADQANQA7AFAAUwAgADEALgAwADQANQA7AGgAbwB0AGMAbwBuAHYAIAAxAC4AMAAuADgAMgA7AG0AYQBrAGUAbwB0AGYALgBsAGkAYgAyAC4ANQAuADYAMwA0ADAANgBBAGQAbwBiAGUAQgBsAGEAbgBrAEEAZABvAGIAZQAgAFMAeQBzAHQAZQBtAHMAIABJAG4AYwBvAHIAcABvAHIAYQB0AGUAZABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBkAG8AYgBlAC4AYwBvAG0ALwB0AHkAcABlAC8AVABoAGkAcwAgAEYAbwBuAHQAIABTAG8AZgB0AHcAYQByAGUAIABpAHMAIABsAGkAYwBlAG4AcwBlAGQAIAB1AG4AZABlAHIAIAB0AGgAZQAgAFMASQBMACAATwBwAGUAbgAgAEYAbwBuAHQAIABMAGkAYwBlAG4AcwBlACwAIABWAGUAcgBzAGkAbwBuACAAMQAuADEALgAgAFQAaABpAHMAIABGAG8AbgB0ACAAUwBvAGYAdAB3AGEAcgBlACAAaQBzACAAZABpAHMAdAByAGkAYgB1AHQAZQBkACAAbwBuACAAYQBuACAAIgBBAFMAIABJAFMAIgAgAEIAQQBTAEkAUwAsACAAVwBJAFQASABPAFUAVAAgAFcAQQBSAFIAQQBOAFQASQBFAFMAIABPAFIAIABDAE8ATgBEAEkAVABJAE8ATgBTACAATwBGACAAQQBOAFkAIABLAEkATgBEACwAIABlAGkAdABoAGUAcgAgAGUAeABwAHIAZQBzAHMAIABvAHIAIABpAG0AcABsAGkAZQBkAC4AIABTAGUAZQAgAHQAaABlACAAUwBJAEwAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQBjAGUAbgBzAGUAIABmAG8AcgAgAHQAaABlACAAcwBwAGUAYwBpAGYAaQBjACAAbABhAG4AZwB1AGEAZwBlACwAIABwAGUAcgBtAGkAcwBzAGkAbwBuAHMAIABhAG4AZAAgAGwAaQBtAGkAdABhAHQAaQBvAG4AcwAgAGcAbwB2AGUAcgBuAGkAbgBnACAAeQBvAHUAcgAgAHUAcwBlACAAbwBmACAAdABoAGkA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wwDEAMUAxgDHAMgAyQDKAMsAzADNAM4AzwDQANEA0gDTANQA1QDWANcA2ADZANoA2wDcAN0A3gDfAOAA4QDiAOMA5ADlAOYA5wDoAOkA6gDrAOwA7QDuAO8A8ADxAPIA8wD0APUA9gD3APgA+QD6APsA/AD9AP4A/wEAAQEBAgEDAQQBBQEGAQcBCAEJAQoBCwEMAQ0BDgEPARABEQESARMBFAEVARYBFwEYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BLwEwATEBMgEzATQBNQE2ATcBOAE5AToBOwE8AT0BPgE/AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwBTQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8BgAGBAYIBgwGEAYUBhgGHAYgBiQGKAYsBjAGNAY4BjwGQAZEBkgGTAZQBlQGWAZcBmAGZAZoBmwGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgGrAawBrQGuAa8BsAGxAbIBswG0AbUBtgG3AbgBuQG6AbsBvAG9Ab4BvwHAAcEBwgHDAcQBxQHGAccByAHJAcoBywHMAc0BzgHPAdAB0QHSAdMB1AHVAdYB1wHYAdkB2gHbAdwB3QHeAd8B4AHhAeIB4wHkAeUB5gHnAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AgACAQICAgMCBAIFAgYCBwIIAgkCCgILAgwCDQIOAg8CEAIRAhICEwIUAhUCFgIXAhgCGQIaAhsCHAIdAh4CHwIgAiECIgIjAiQCJQImAicCKAIpAioCKwIsAi0CLgIvAjACMQIyAjMCNAI1AjYCNwI4AjkCOgI7AjwCPQI+Aj8CQAJBAkICQwJEAkUCRgJHAkgCSQJKAksCTAJNAk4CTwJQAlECUgJTAlQCVQJWAlcCWAJZAloCWwJcAl0CXgJfAmACYQJiAmMCZAJlAmYCZwJoAmkCagJrAmwCbQJuAm8CcAJxAnICcwJ0AnUCdgJ3AngCeQJ6AnsCfAJ9An4CfwKAAoECggKDAoQChQKGAocCiAKJAooCiwKMAo0CjgKPApACkQKSApMClAKVApYClwKYApkCmgKbApwCnQKeAp8CoAKhAqICowKkAqUCpgKnAqgCqQKqAqsCrAKtAq4CrwKwArECsgKzArQCtQK2ArcCuAK5AroCuwK8Ar0CvgK/AsACwQLCAsMCxALFAsYCxwLIAskCygLLAswCzQLOAs8C0ALRAtIC0wLUAtUC1gLXAtgC2QLaAtsC3ALdAt4C3wLgAuEC4gLjAuQC5QLmAucC6ALpAuoC6wLsAu0C7gLvAvAC8QLyAvMC9AL1AvYC9wL4AvkC+gL7AvwC/QL+Av8DAAMBAwIDAwMEAwUDBgMHAwgDCQMKAwsDDAMNAw4DDwMQAxEDEgMTAxQDFQMWAxcDGAMZAxoDGwMcAx0DHgMfAyADIQMiAyMDJAMlAyYDJwMoAykDKgMrAywDLQMuAy8DMAMxAzIDMwM0AzUDNgM3AzgDOQM6AzsDPAM9Az4DPwNAA0EDQgNDA0QDRQNGA0cDSANJA0oDSwNMA00DTgNPA1ADUQNSA1MDVANVA1YDVwNYA1kDWgNbA1wDXQNeA18DYANhA2IDYwNkA2UDZgNnA2gDaQNqA2sDbANtA24DbwNwA3EDcgNzA3QDdQN2A3cDeAN5A3oDewN8A30DfgN/A4ADgQOCA4MDhAOFA4YDhwOIA4kDigOLA4wDjQOOA48DkAORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDogOjA6QDpQOmA6cDqAOpA6oDqwOsA60DrgOvA7ADsQOyA7MDtAO1A7YDtwO4A7kDugO7A7wDvQO+A78DwAPBA8IDwwPEA8UDxgPHA8gDyQPKA8sDzAPNA84DzwPQA9ED0gPTA9QD1QPWA9cD2APZA9oD2wPcA90D3gPfA+AD4QPiA+MD5APlA+YD5wPoA+kD6gPrA+wD7QPuA+8D8APxA/ID8wP0A/UD9gP3A/gD+QP6A/sD/AP9A/4D/wQABAEEAgQDBAQEBQQGBAcECAQJBAoECwQMBA0EDgQPBBAEEQQSBBMEFAQVBBYEFwQYBBkEGgQbBBwEHQQeBB8EIAQhBCIEIwQkBCUEJgQnBCgEKQQqBCsELAQtBC4ELwQwBDEEMgQzBDQENQQ2BDcEOAQ5BDoEOwQ8BD0EPgQ/BEAEQQRCBEMERARFBEYERwRIBEkESgRLBEwETQROBE8EUARRBFIEUwRUBFUEVgRXBFgEWQRaBFsEXARdBF4EXwRgBGEEYgRjBGQEZQRmBGcEaARpBGoEawRsBG0EbgRvBHAEcQRyBHMEdAR1BHYEdwR4BHkEegR7BHwEfQR+BH8EgASBBIIEgwSEBIUEhgSHBIgEiQSKBIsEjASNBI4EjwSQBJEEkgSTBJQElQSWBJcEmASZBJoEmwScBJ0EngSfBKAEoQSiBKMEpASlBKYEpwSoBKkEqgSrBKwErQSuBK8EsASxBLIEswS0BLUEtgS3BLgEuQS6BLsEvAS9BL4EvwTABMEEwgTDBMQExQTGBMcEyATJBMoEywTMBM0EzgTPBNAE0QTSBNME1ATVBNYE1wTYBNkE2gTbBNwE3QTeBN8E4AThBOIE4wTkBOUE5gTnBOgE6QTqBOsE7ATtBO4E7wTwBPEE8gTzBPQE9QT2BPcE+AT5BPoE+wT8BP0E/gT/BQAFAQUCBQMFBAUFBQYFBwUIBQkFCgULBQwFDQUOBQ8FEAURBRIFEwUUBRUFFgUXBRgFGQUaBRsFHAUdBR4FHwUgBSEFIgUjBSQFJQUmBScFKAUpBSoFKwUsBS0FLgUvBTAFMQUyBTMFNAU1BTYFNwU4BTkFOgU7BTwFPQU+BT8FQAVBBUIFQwVEBUUFRgVHBUgFSQVKBUsFTAVNBU4FTwVQBVEFUgVTBVQFVQVWBVcFWAVZBVoFWwVcBV0FXgVfBWAFYQViBWMFZAVlBWYFZwVoBWkFagVrBWwFbQVuBW8FcAVxBXIFcwV0BXUFdgV3BXgFeQV6BXsFfAV9BX4FfwWABYEFggWDBYQFhQWGBYcFiAWJBYoFiwWMBY0FjgWPBZAFkQWSBZMFlAWVBZYFlwWYBZkFmgWbBZwFnQWeBZ8FoAWhBaIFowWkBaUFpgWnBagFqQWqBasFrAWtBa4FrwWwBbEFsgWzBbQFtQW2BbcFuAW5BboFuwW8Bb0FvgW/BcAFwQXCBcMFxAXFBcYFxwXIBckFygXLBcwFzQXOBc8F0AXRBdIF0wXUBdUF1gXXBdgF2QXaBdsF3AXdBd4F3wXgBeEF4gXjBeQF5QXmBecF6AXpBeoF6wXsBe0F7gXvBfAF8QXyBfMF9AX1BfYF9wX4BfkF+gX7BfwF/QX+Bf8GAAYBBgIGAwYEBgUGBgYHBggGCQYKBgsGDAYNBg4GDwYQBhEGEgYTBhQGFQYWBhcGGAYZBhoGGwYcBh0GHgYfBiAGIQYiBiMGJAYlBiYGJwYoBikGKgYrBiwGLQYuBi8GMAYxBjIGMwY0BjUGNgY3BjgGOQY6BjsGPAY9Bj4GPwZABkEGQgZDBkQGRQZGBkcGSAZJBkoGSwZMBk0GTgZPBlAGUQZSBlMGVAZVBlYGVwZYBlkGWgZbBlwGXQZeBl8GYAZhBmIGYwZkBmUGZgZnBmgGaQZqBmsGbAZtBm4GbwZwBnEGcgZzBnQGdQZ2BncGeAZ5BnoGewZ8Bn0GfgZ/BoAGgQaCBoMGhAaFBoYGhwaIBokGigaLBowGjQaOBo8GkAaRBpIGkwaUBpUGlgaXBpgGmQaaBpsGnAadBp4GnwagBqEGogajBqQGpQamBqcGqAapBqoGqwasBq0GrgavBrAGsQayBrMGtAa1BrYGtwa4BrkGuga7BrwGvQa+Br8GwAbBBsIGwwbEBsUGxgbHBsgGyQbKBssGzAbNBs4GzwbQBtEG0gbTBtQG1QbWBtcG2AbZBtoG2wbcBt0G3gbfBuAG4QbiBuMG5AblBuYG5wboBukG6gbrBuwG7QbuBu8G8AbxBvIG8wb0BvUG9gb3BvgG+Qb6BvsG/Ab9Bv4G/wcABwEHAgcDBwQHBQcGBwcHCAcJBwoHCwcMBw0HDgcPBxAHEQcSBxMHFAcVBxYHFwcYBxkHGgcbBxwHHQceBx8HIAchByIHIwckByUHJgcnBygHKQcqBysHLActBy4HLwcwBzEHMgczBzQHNQc2BzcHOAc5BzoHOwc8Bz0HPgc/B0AHQQdCB0MHRAdFB0YHRwdIB0kHSgdLB0wHTQdOB08HUAdRB1IHUwdUB1UHVgdXB1gHWQdaB1sHXAddB14HXwdgB2EHYgdjB2QHZQdmB2cHaAdpB2oHawdsB20HbgdvB3AHcQdyB3MHdAd1B3YHdwd4B3kHegd7B3wHfQd+B38HgAeBB4IHgweEB4UHhgeHB4gHiQeKB4sHjAeNB44HjweQB5EHkgeTB5QHlQeWB5cHmAeZB5oHmwecB50HngefB6AHoQeiB6MHpAelB6YHpweoB6kHqgerB6wHrQeuB68HsAexB7IHswe0B7UHtge3B7gHuQe6B7sHvAe9B74HvwfAB8EHwgfDB8QHxQfGB8cHyAfJB8oHywfMB80HzgfPB9AH0QfSB9MH1AfVB9YH1wfYB9kH2gfbB9wH3QfeB98H4AfhB+IH4wfkB+UH5gfnB+gH6QfqB+sH7AftB+4H7wfwB/EH8gfzB/QH9Qf2B/cH+Af5B/oH+wf8B/0H/gf/CAAIAQgCCAMIBAgFCAYIBwgICAkICggLCAwIDQgOCA8IEAgRCBIIEwgUCBUIFggXCBgIGQgaCBsIHAgdCB4IHwggCCEIIggjCCQIJQgmCCcIKAgpCCoIKwgsCC0ILggvCDAIMQgyCDMINAg1CDYINwg4CDkIOgg7CDwIPQg+CD8IQAhBCEIIQwhECEUIRghHCEgISQhKCEsg+wy3+iS3AfcQt/kstwP3EPoEFf58+YT6fAf9WP4nFfnSB/fF/DMFprAV+8X4NwX49gamYhX90gf7xfgzBXBmFffF/DcF/PYGDg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4ODg4OAAEBAQr4HwwmmhwZLRL7joscBUaLBr0KvQv65xUD6AB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA=="); +} + +#font-validator { + padding: 0; + margin: 0; + font-size: 18px; + + position: absolute; + top: -100px; + left: -100px +} diff --git a/app/editor/base/font.js b/app/editor/base/font.js index 84ef628b..5d02b1b0 100644 --- a/app/editor/base/font.js +++ b/app/editor/base/font.js @@ -16,16 +16,18 @@ goog.provide('thin.Font'); goog.require('goog.array'); +goog.require('goog.Disposable'); goog.require('thin.platform.Font'); +goog.require('thin.platform.FontValidator'); /** * @param {string} family * @param {string=} opt_name - * @param {boolean=} opt_builtin * @constructor + * @extends {goog.Disposable} */ -thin.Font = function(family, opt_name, opt_builtin) { +thin.Font = function(family, opt_name) { /** * @type {string} * @private @@ -37,20 +39,15 @@ thin.Font = function(family, opt_name, opt_builtin) { * @private */ this.name_ = opt_name || family; - - /** - * @type {boolean} - * @private - */ - this.builtin_ = opt_builtin || false; }; +goog.inherits(thin.Font, goog.Disposable); /** * @type {Array.} * @private */ -thin.Font.fontRegistry_ = []; +thin.Font.builtinFontRegistry_ = []; /** @@ -63,12 +60,11 @@ thin.Font.defaultFont_; /** * @param {string} family * @param {string=} opt_name - * @param {boolean=} opt_builtin * @return {thin.Font} */ -thin.Font.register = function(family, opt_name, opt_builtin) { - var font = new thin.Font(family, opt_name || family, opt_builtin); - thin.Font.fontRegistry_.push(font); +thin.Font.register = function(family, opt_name) { + var font = new thin.Font(family, opt_name || family); + thin.Font.builtinFontRegistry_.push(font); return font; }; @@ -78,12 +74,12 @@ thin.Font.init = function() { font.defaultFont_ = font.register('Helvetica', null, true); - font.register('Courier New', null, true); - font.register('Times New Roman', null, true); - font.register('IPAMincho', 'IPA ' + thin.t('font_mincho'), true); - font.register('IPAPMincho', 'IPA P' + thin.t('font_mincho'), true); - font.register('IPAGothic', 'IPA ' + thin.t('font_gothic'), true); - font.register('IPAPGothic', 'IPA P' + thin.t('font_gothic'), true); + font.register('Courier New'); + font.register('Times New Roman'); + font.register('IPAMincho', 'IPA ' + thin.t('font_mincho')); + font.register('IPAPMincho', 'IPA P' + thin.t('font_mincho')); + font.register('IPAGothic', 'IPA ' + thin.t('font_gothic')); + font.register('IPAPGothic', 'IPA P' + thin.t('font_gothic')); }; @@ -98,8 +94,30 @@ thin.Font.getDefaultFontFamily = function() { /** * @return {Array.} */ -thin.Font.getFonts = function() { - return thin.Font.fontRegistry_; +thin.Font.getBuiltinFonts = function() { + return thin.Font.builtinFontRegistry_; +}; + + +/** + * @param {string} family + * @return {boolean} + */ +thin.Font.isRegistered = function (family) { + var detected = thin.Font.findFontByFamily(family); + return detected !== null; +}; + + +/** + * @param {string} family + * @return {thin.Font?} + */ +thin.Font.findFontByFamily = function (family) { + return goog.array.find(thin.Font.fontRegistry_, + function (font) { + return font.getFamily() == family; + }); }; @@ -107,10 +125,7 @@ thin.Font.getFonts = function() { * @type {Object.} * @private */ -thin.Font.infoRegistry_ = { - ascent: {}, - height: {} -}; +thin.Font.infoRegistry_ = {}; /** @@ -131,28 +146,33 @@ thin.Font.generateRegistryKey_ = function(var_args) { */ thin.Font.getAscent = function(family, fontSize, isBold) { var registryKey = thin.Font.generateRegistryKey_(family, fontSize, isBold); - var ascent = thin.Font.infoRegistry_.ascent[registryKey]; - if (!goog.isDef(ascent)) { - ascent = thin.platform.Font.getAscent(family, fontSize, isBold); - thin.Font.infoRegistry_.ascent[registryKey] = ascent; + var info = thin.Font.infoRegistry_[registryKey]; + + if (!goog.isDef(info)) { + info = thin.platform.Font.getMetrics(family, fontSize, isBold); + thin.Font.infoRegistry_[registryKey] = info; } - return ascent; + + return info.ascent; }; /** * @param {string} family * @param {number} fontSize + * @param {boolean} isBold * @return {number} */ -thin.Font.getHeight = function(family, fontSize) { +thin.Font.getHeight = function(family, fontSize, isBold) { var registryKey = thin.Font.generateRegistryKey_(family, fontSize); - var height = thin.Font.infoRegistry_.height[registryKey]; - if (!goog.isDef(height)) { - height = thin.platform.Font.getHeight(family, fontSize); - thin.Font.infoRegistry_.height[registryKey] = height; + var info = thin.Font.infoRegistry_[registryKey]; + + if (!goog.isDef(info)) { + info = thin.platform.Font.getMetrics(family, fontSize, isBold); + thin.Font.infoRegistry_[registryKey] = info; } - return height; + + return info.height; }; @@ -175,6 +195,15 @@ thin.Font.prototype.getName = function() { /** * @return {boolean} */ -thin.Font.prototype.isBuiltin = function() { - return this.builtin_; +thin.Font.prototype.isValid = function () { + return thin.platform.FontValidator.validate(this.family_); +}; + + +/** @override */ +thin.Font.prototype.disposeInternal = function () { + goog.base(this, 'disposeInternal'); + + this.family_ = null; + this.name_ = null; }; diff --git a/app/editor/base/platform/font.js b/app/editor/base/platform/font.js index da4fd832..0ae5ce8a 100644 --- a/app/editor/base/platform/font.js +++ b/app/editor/base/platform/font.js @@ -17,70 +17,32 @@ goog.provide('thin.platform.Font'); goog.require('goog.dom'); goog.require('thin.platform'); -goog.require('thin.core.TextHelper'); /** - * @type {string} - * @private - */ -thin.platform.FIRST_LINE_TEXT_ = 'Agjぽ'; - - -/** - * @param {string} family - * @param {number} fontSize - * @param {boolean} isBold + * @param {string} family + * @param {number} fontSize + * @param {boolean} isBold * @return {Object} */ -thin.platform.Font.getTextLineSpec = function(family, fontSize, isBold) { - var layout = thin.core.getActiveWorkspace().getLayout(); - - var textHelper = new thin.core.TextHelper(layout); - textHelper.setFontSize(fontSize); - textHelper.setFontFamily(family); - textHelper.setFontBold(isBold); - textHelper.setVisibled(false); - textHelper.setFirstLine(thin.platform.FIRST_LINE_TEXT_); - - var helper = layout.getHelpers(); - helper.appendBack(textHelper); - - var firstLine = textHelper.getFirstLine(); - var spec = { - height: firstLine.getHeight(), - ascent: firstLine.getAscent(), - descent: firstLine.getDescent() +thin.platform.Font.getMetrics = function (family, fontSize, isBold) { + var FontMetrics = thin.app('FontMetrics'); + + FontMetrics.settings.chars.ascent = 'ぽ'; + + var spec = /** @type {Object} */ ( + FontMetrics({ + 'fontFamily': family, + 'fontWeight': isBold ? 'bold' : 'normal' + }) + ); + + var ascent = Math.abs(spec.ascent * fontSize); + var descent = Math.abs(spec.descent * fontSize); + + return { + ascent: ascent, + descent: descent, + height: ascent + descent }; - - goog.dom.removeNode(textHelper.getElement()); - // cannot be deleted in ES5 strict mode - firstLine = null; - - return spec; -}; - - -/** - * @param {string} family - * @param {number} fontSize - * @return {number} - */ -thin.platform.Font.getHeight = function(family, fontSize) { - var spec = thin.platform.Font.getTextLineSpec(family, fontSize, false); - return spec.height; -}; - - -/** - * @param {string} family - * @param {number} fontSize - * @param {boolean} isBold - * @return {number} - */ -thin.platform.Font.getAscent = function( - family, fontSize, isBold) { - - var spec = thin.platform.Font.getTextLineSpec(family, fontSize, isBold); - return spec.ascent; }; diff --git a/app/editor/base/platform/fontvalidator.js b/app/editor/base/platform/fontvalidator.js new file mode 100644 index 00000000..c3ef2d3a --- /dev/null +++ b/app/editor/base/platform/fontvalidator.js @@ -0,0 +1,68 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.platform.FontValidator'); + +goog.require('goog.dom'); +goog.require('goog.style'); + + +/** + * @constructor + */ +thin.platform.FontValidator = function () { + /** + * @type {Element} + * @private + */ + this.element_ = goog.dom.getElement('font-validator'); +}; +goog.addSingletonGetter(thin.platform.FontValidator); + + +/** + * @param {string} family + * @return {boolean} + */ +thin.platform.FontValidator.validate = function (family) { + return thin.platform.FontValidator.getInstance().validate(family); +}; + + +/** + * @define {string} + */ +thin.platform.FontValidator.BLANK_FONT_FAMILY = 'AdobeBlank'; + + +/** + * @param {string} family + * @return {boolean} + */ +thin.platform.FontValidator.prototype.validate = function (family) { + this.setFontFamily_(family); + return goog.style.getSize(this.element_).width > 1; +}; + + +/** + * @param {string} family + * @return {void} + * @private + */ +thin.platform.FontValidator.prototype.setFontFamily_ = function (family) { + var style = family + ',' + thin.platform.FontValidator.BLANK_FONT_FAMILY; + goog.style.setStyle(this.element_, 'font-family', style); +}; diff --git a/app/editor/boot.js b/app/editor/boot.js index 690721fe..85d3b754 100644 --- a/app/editor/boot.js +++ b/app/editor/boot.js @@ -47,6 +47,7 @@ goog.require('thin.ui.ToolbarSplitToggleButton'); goog.require('thin.ui.ToolbarToggleIconButton'); goog.require('thin.ui.ToolbarSelect'); goog.require('thin.ui.ToolbarFontSelect'); +goog.require('thin.ui.toolbar.ComboBox'); goog.require('thin.ui.ToggleGroup'); goog.require('thin.ui.MenuItem'); goog.require('thin.ui.MenuLinkItem'); @@ -819,7 +820,7 @@ thin.init_ = function() { }); // Zoom rate var toolZoomRate = toolbar.setupChild('zoom-rate', - new thin.ui.ComboBox(), dom.getElement('tbar-zoom-rate'), + new thin.ui.toolbar.ComboBox(), dom.getElement('tbar-zoom-rate'), function(combobox) { var zoomRateList = ['25', '50', '75', '100', '150', '200', '400', '600']; var comboboxItem; @@ -909,7 +910,7 @@ thin.init_ = function() { selectbox.setWidth(170); }); - toolFamily.addEventListener(componentEventType.ACTION, function(e) { + toolFamily.addEventListener(componentEventType.CHANGE, function(e) { var workspace = thin.core.getActiveWorkspace(); if (workspace) { var selectedFamily = toolFamily.getValue(); @@ -922,7 +923,7 @@ thin.init_ = function() { // Font size var toolSize = toolbar.setupChild('font-size', - new thin.ui.ComboBox(), dom.getElement('tbar-font-size'), + new thin.ui.toolbar.ComboBox(), dom.getElement('tbar-font-size'), function(combobox) { var comboboxItem; goog.array.forEach(thin.core.FontStyle.FONTSIZE_LIST, function(fontSize) { @@ -1317,7 +1318,7 @@ thin.init_ = function() { localeSelectBox.setTextAlignLeft(); dialog.addChild(localeSelectBox, false); - var locales = /** @type {Array} */ (thin.callApp('getLocales')); + var locales = /** @type {Array} */ (thin.callAppMethod('getLocales')); goog.array.forEach(locales, function(locale) { localeSelectBox.addItem( diff --git a/app/editor/core/abstracttext.js b/app/editor/core/abstracttext.js index 857294fa..a17b593e 100644 --- a/app/editor/core/abstracttext.js +++ b/app/editor/core/abstracttext.js @@ -122,35 +122,6 @@ thin.core.AbstractText.prototype.getHeight = function() { * @return {number} */ thin.core.AbstractText.prototype.getWidth = function() { - this.width_ = this.getBBox().width; + this.width_ = this.getBBox().width * 1.01; return this.width_; }; - - -/** - * @return {number} - */ -thin.core.AbstractText.prototype.getBaseLine = function() { - var element = this.getElement(); - if (element.hasAttribute('y')) { - return Number(this.getLayout().getElementAttribute(element, 'y')); - } else { - return 0; - } -}; - - -/** - * @return {number} - */ -thin.core.AbstractText.prototype.getAscent = function() { - return Math.round(this.getBaseLine() - this.getBBox().y); -}; - - -/** - * @return {number} - */ -thin.core.AbstractText.prototype.getDescent = function() { - return this.getHeight() - this.getAscent(); -}; diff --git a/app/editor/core/abstracttextgroup.js b/app/editor/core/abstracttextgroup.js index e6510bdf..16d0eb2a 100644 --- a/app/editor/core/abstracttextgroup.js +++ b/app/editor/core/abstracttextgroup.js @@ -129,7 +129,7 @@ thin.core.AbstractTextGroup.prototype.setTextLineHeightRatio = function(ratio) { } else { var layout = this.getLayout(); var numRatio = Number(ratio); - var heightAt = thin.Font.getHeight(this.getFontFamily(), this.getFontSize()); + var heightAt = thin.Font.getHeight(this.getFontFamily(), this.getFontSize(), this.isFontBold()); layout.setElementAttributes(element, { 'x-line-height': heightAt * numRatio diff --git a/app/editor/core/action.js b/app/editor/core/action.js index 8cfc352b..e6c57531 100644 --- a/app/editor/core/action.js +++ b/app/editor/core/action.js @@ -384,7 +384,7 @@ thin.core.Action.prototype.actionSetFontSize = function(newFontSize) { var setFontSizeTblockShape = function(shape, fontSize) { shape.setFontSize(fontSize); if (!shape.isMultiMode()) { - shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize)); + shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize, shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setHeight(shape.getHeight()); } @@ -397,7 +397,7 @@ thin.core.Action.prototype.actionSetFontSize = function(newFontSize) { */ var setPageNumberFontSize = function(shape, fontSize) { shape.setFontSize(fontSize); - shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize)); + shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), fontSize, shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setHeight(shape.getHeight()); } @@ -525,7 +525,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { var setFontFamilyTblockShape = function(shape, fontFamily) { shape.setFontFamily(fontFamily); if (!shape.isMultiMode()) { - shape.setHeight(thin.Font.getHeight(fontFamily, shape.getFontSize())); + shape.setHeight(thin.Font.getHeight(fontFamily, shape.getFontSize(), shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setHeight(shape.getHeight()); } @@ -538,6 +538,7 @@ thin.core.Action.prototype.actionSetFontFamily = function(newFontFamily) { */ var setPageNumberFontFamily = function(shape, fontFamily) { shape.setFontFamily(fontFamily); + shape.setHeight(thin.Font.getHeight(fontFamily, shape.getFontSize(), shape.isFontBold())); if (isMultipleSelect) { shape.getTargetOutline().setBounds(shape.getBounds()); } diff --git a/app/editor/core/layout.js b/app/editor/core/layout.js index 14f5f68d..bd20dae3 100644 --- a/app/editor/core/layout.js +++ b/app/editor/core/layout.js @@ -39,6 +39,7 @@ goog.require('thin.core.StateManager'); goog.require('thin.core.ShapeIdManager'); goog.require('thin.core.ShapeIdManager.DefaultPrefix'); goog.require('thin.core.ClipboardShapeManager'); +goog.require('thin.core.layout.AllUsedFontFamilies'); /** @@ -378,6 +379,23 @@ thin.core.Layout.prototype.createHelpersElement = function(tagName, attrs) { }; +/** + * @return {Array.} + */ +thin.core.Layout.prototype.getUsedCustomFonts = function () { + var customFonts = this.getWorkspace().getCustomFonts().get(); + var allUsedFontFamilies = thin.core.layout.AllUsedFontFamilies.get(this); + + var usedCustomFonts = goog.array.filter(customFonts, function (font) { + return goog.array.contains(allUsedFontFamilies, font.getFamily()); + }); + + goog.array.sort(usedCustomFonts); + + return usedCustomFonts; +}; + + /** * @return {Object} */ diff --git a/app/editor/core/layout/allusedfontfamilies.js b/app/editor/core/layout/allusedfontfamilies.js new file mode 100644 index 00000000..51617416 --- /dev/null +++ b/app/editor/core/layout/allusedfontfamilies.js @@ -0,0 +1,113 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.core.layout.AllUsedFontFamilies'); + +goog.require('goog.array'); +goog.require('goog.Disposable'); +goog.require('thin.core.ListShape'); +goog.require('thin.core.AbstractTextGroup'); + + +/** + * @param {thin.core.Layout} layout + * @constructor + * @extends {goog.Disposable} + */ +thin.core.layout.AllUsedFontFamilies = function (layout) { + /** + * @type {thin.core.layout} + * @private + */ + this.layout_ = layout; +}; +goog.inherits(thin.core.layout.AllUsedFontFamilies, goog.Disposable); + + +/** + * @param {thin.core.layout} layout + * @return {Array.} + */ +thin.core.layout.AllUsedFontFamilies.get = function (layout) { + var action = new thin.core.layout.AllUsedFontFamilies(layout); + return action.get(); +}; + + +/** + * @return {Array.} + */ +thin.core.layout.AllUsedFontFamilies.prototype.get = function () { + var shapesInLayout = this.layout_.getManager().getShapesManager().get(); + return this.get_(shapesInLayout); +}; + + +/** + * @param {Array} shapes Array. + * @private + */ +thin.core.layout.AllUsedFontFamilies.prototype.get_ = function (shapes) { + var targetShapes = this.filterTarget_(shapes); + + var families = goog.array.map(targetShapes, + function (shape) { + if (shape instanceof thin.core.ListShape) { + return /** @type {Array.} */(this.getInListShape_(shape)); + } else if (shape instanceof thin.core.AbstractTextGroup) { + return /** @type {string} */(shape.getFontFamily()); + } + }, this); + + return goog.array.flatten(families); +}; + + +/** + * @param {thin.core.ListShape} shape + * @return {Array.} + */ +thin.core.layout.AllUsedFontFamilies.prototype.getInListShape_ = function (shape) { + var familiesEachSection = []; + + shape.forEachSectionShape(function (section) { + familiesEachSection.push(this.get_(section.getManager().getShapesManager().get())); + }, this) + + return goog.array.flatten(familiesEachSection); +}; + + +/** + * @param {Array} shapes Array. + * @return {Array} Filtered shapes + * @private + */ +thin.core.layout.AllUsedFontFamilies.prototype.filterTarget_ = function (shapes) { + return goog.array.filter(shapes, function (shape) { + return shape instanceof thin.core.ListShape || shape instanceof thin.core.AbstractTextGroup; + }); +}; + + +/** + * @override + */ +thin.core.layout.AllUsedFontFamilies.prototype.disposeInternal = function () { + goog.base(this, 'disposeInternal'); + + this.layout_ = null; + delete this.layout_; +}; diff --git a/app/editor/core/multipleshapeshelper.js b/app/editor/core/multipleshapeshelper.js index 22ef1470..3ce4597a 100644 --- a/app/editor/core/multipleshapeshelper.js +++ b/app/editor/core/multipleshapeshelper.js @@ -867,8 +867,7 @@ thin.core.MultipleShapesHelper.prototype.createPropertyComponent_ = function() { if (shape.instanceOfTblockShape()) { shape.setMultiMode(multipleMode); if (!multipleMode) { - shape.setHeight(thin.Font.getHeight( - shape.getFontFamily(), shape.getFontSize())); + shape.setHeight(thin.Font.getHeight(shape.getFontFamily(), shape.getFontSize(), shape.isFontBold())); shape.getTargetOutline().setHeight(shape.getHeight()); } } diff --git a/app/editor/core/pagenumberoutline.js b/app/editor/core/pagenumberoutline.js index 8cc1c428..413dc3aa 100644 --- a/app/editor/core/pagenumberoutline.js +++ b/app/editor/core/pagenumberoutline.js @@ -50,7 +50,8 @@ thin.core.PageNumberOutline.prototype.setBoundsByCoordinate = function(startPosX thin.numberWithPrecision(Math.abs(startPosX - clientPosX)), thin.Font.getHeight( workspace.getUiStatusForFontFamily(), - workspace.getUiStatusForFontSize())); + workspace.getUiStatusForFontSize(), + workspace.getUiStatusForBold())); this.setBounds(bounds); }; diff --git a/app/editor/core/tblockoutline.js b/app/editor/core/tblockoutline.js index 97255722..ceb56b63 100644 --- a/app/editor/core/tblockoutline.js +++ b/app/editor/core/tblockoutline.js @@ -49,7 +49,9 @@ thin.core.TblockOutline.prototype.setBoundsByCoordinate = function(startPosX, st thin.numberWithPrecision(Math.abs(startPosX - clientPosX)), thin.Font.getHeight( workspace.getUiStatusForFontFamily(), - workspace.getUiStatusForFontSize()))); + workspace.getUiStatusForFontSize(), + workspace.getUiStatusForBold() + ))); }; @@ -107,4 +109,4 @@ thin.core.TblockOutline.prototype.getInitShapeProperties = function() { thin.core.TblockOutline.prototype.disposeInternal = function() { thin.core.TblockOutline.superClass_.disposeInternal.call(this); this.disposeInternalForOutline(); -}; \ No newline at end of file +}; diff --git a/app/editor/core/tblockshape.js b/app/editor/core/tblockshape.js index 6e4cfe03..ab594ae2 100644 --- a/app/editor/core/tblockshape.js +++ b/app/editor/core/tblockshape.js @@ -1071,7 +1071,7 @@ thin.core.TblockShape.prototype.createPropertyComponent_ = function() { scope.setHeight(captureHeight); } else { scope.setHeight(thin.Font.getHeight( - scope.getFontFamily(), scope.getFontSize())); + scope.getFontFamily(), scope.getFontSize(), shape.isFontBold())); } scope.updateToolbarUI(); diff --git a/app/editor/core/texthelper.js b/app/editor/core/texthelper.js deleted file mode 100644 index 2709b05a..00000000 --- a/app/editor/core/texthelper.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (C) 2011 Matsukei Co.,Ltd. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -goog.provide('thin.core.TextHelper'); - -goog.require('thin.core.TextLineShape'); -goog.require('thin.core.AbstractTextGroup'); - - -/** - * @param {thin.core.Layout} layout - * @constructor - * @extends {thin.core.AbstractTextGroup} - */ -thin.core.TextHelper = function(layout) { - goog.base(this, this.createElement_(layout), layout); -}; -goog.inherits(thin.core.TextHelper, thin.core.AbstractTextGroup); - - -/** - * @type {thin.core.TextLineShape} - * @private - */ -thin.core.TextHelper.prototype.firstLine_ = null; - -/** - * @param {thin.core.Layout} layout - * @private - */ -thin.core.TextHelper.prototype.createElement_ = function(layout) { - return layout.createSvgElement('g', { - 'stroke-width': 0 - }); -}; - - -/** - * @param {string} content - */ -thin.core.TextHelper.prototype.setFirstLine = function(content) { - goog.array.forEachRight(this.getElement().childNodes, function(element) { - if (element.tagName == 'text') { - goog.dom.removeNode(element); - } - }); - - var layout = this.getLayout(); - var firstLine = new thin.core.TextLineShape( - layout.createSvgElement('text'), layout, 0); - firstLine.setText(content); - layout.appendChild(firstLine, this); - - if (this.firstLine_) { - this.firstLine_.dispose(); - delete this.firstLine_; - } - - this.firstLine_ = firstLine; -}; - - -/** - * @return {thin.core.TextLineShape} - */ -thin.core.TextHelper.prototype.getFirstLine = function() { - return this.firstLine_; -}; - - -/** @inheritDoc */ -thin.core.TextHelper.prototype.disposeInternal = function() { - this.firstLine_.dispose(); - delete this.firstLine_; - - goog.base(this, 'disposeInternal'); -}; diff --git a/app/editor/core/textshape.js b/app/editor/core/textshape.js index 3f907d25..50fdb93d 100644 --- a/app/editor/core/textshape.js +++ b/app/editor/core/textshape.js @@ -202,8 +202,8 @@ thin.core.TextShape.prototype.setTop = function(top) { var isBold = this.isFontBold(); var ascent = thin.Font.getAscent(family, fontSize, isBold); - var heightAt = thin.Font.getHeight(family, fontSize); - var translateY = thin.numberWithPrecision(heightAt * ratio, 2); + var height = thin.Font.getHeight(family, fontSize, isBold); + var translateY = thin.numberWithPrecision(height * ratio, 2); var y = thin.numberWithPrecision(xTop + ascent, 2); goog.array.forEach(this.getTextLineShapes(), function(textline, index) { @@ -257,16 +257,16 @@ thin.core.TextShape.prototype.getHeightInternal = function() { } ratio = Number(ratio); - var heightAt = thin.Font.getHeight(this.getFontFamily(), this.getFontSize()); + var height = thin.Font.getHeight(this.getFontFamily(), this.getFontSize(), this.isFontBold()); var lineCount = this.getTextLineShapes().length; if (ratio >= 1) { - var height = thin.numberWithPrecision((heightAt * ratio) * lineCount); - var diff = thin.numberWithPrecision(heightAt * (ratio - 1), 2); + var height = thin.numberWithPrecision((height * ratio) * lineCount); + var diff = thin.numberWithPrecision(height * (ratio - 1), 2); height = thin.numberWithPrecision(height - diff); } else { - var height = thin.numberWithPrecision(heightAt * lineCount); - var diff = thin.numberWithPrecision(heightAt * (1 - ratio) * (lineCount - 1), 2); + var height = thin.numberWithPrecision(height * lineCount); + var diff = thin.numberWithPrecision(height * (1 - ratio) * (lineCount - 1), 2); height = thin.numberWithPrecision(height - diff); } diff --git a/app/editor/core/workspace/customfontregistry.js b/app/editor/core/workspace/customfontregistry.js new file mode 100644 index 00000000..2d29fa22 --- /dev/null +++ b/app/editor/core/workspace/customfontregistry.js @@ -0,0 +1,75 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.core.workspace.CustomFontRegistry'); + +goog.require('goog.Disposable'); +goog.require('thin.Font'); + + +/** + * @param {Array.=} opt_families + * @extends {goog.Disposable} + * @constructor + */ +thin.core.workspace.CustomFontRegistry = function (opt_families) { + goog.base(this); + + /** + * @type {Array.} + * @private + */ + this.fonts_ = goog.array.map(opt_families || [], + function (family) { + return new thin.Font(family); + }); +}; +goog.inherits(thin.core.workspace.CustomFontRegistry, goog.Disposable); + + +/** + * @param {string} fontFamily + */ +thin.core.workspace.CustomFontRegistry.prototype.register = function (fontFamily) { + this.fonts_.push(new thin.Font(fontFamily)); +}; + + +/** + * @return {Array.} + */ +thin.core.workspace.CustomFontRegistry.prototype.get = function () { + return this.fonts_; +}; + + +/** + * @param {string} fontFamily + * @return {boolean} + */ +thin.core.workspace.CustomFontRegistry.prototype.contains = function (fontFamily) { + var families = goog.array.map(this.fonts_, function (font) { font.getFamily() }); + return goog.array.contains(families, fontFamily); +}; + + +/** + * @override + */ +thin.core.workspace.CustomFontRegistry.prototype.disposeInternal = function () { + goog.base(this, 'disposeInternal'); + + this.fonts_ = null; +}; diff --git a/app/editor/core/workspace/workspace.js b/app/editor/core/workspace/workspace.js index 4ac676f3..0616d860 100644 --- a/app/editor/core/workspace/workspace.js +++ b/app/editor/core/workspace/workspace.js @@ -37,6 +37,7 @@ goog.require('thin.layout.FormatPage.PaperName'); goog.require('thin.layout.FormatPage.DirectionType'); goog.require('thin.layout.document'); goog.require('thin.Font'); +goog.require('thin.core.workspace.CustomFontRegistry'); /** @@ -59,6 +60,12 @@ thin.core.Workspace = function(format, opt_file) { this.setFile(new thin.layout.File()); } + /** + * @type {thin.core.workspace.CustomFontRegistry} + * @private + */ + this.customFonts_ = new thin.core.workspace.CustomFontRegistry(format.getCustomFonts()); + /** * @type {string} * @private @@ -260,10 +267,12 @@ thin.core.Workspace.prototype.handleUndoRedoKeyEvent_ = function(e) { case keyCodes.Z: this.undo(); this.enablingOnceKeyEventHandling_(true); + e.preventDefault(); break; case keyCodes.Y: this.redo(); this.enablingOnceKeyEventHandling_(true); + e.preventDefault(); break; } } @@ -348,6 +357,14 @@ thin.core.Workspace.create = function(file) { }; +/** + * @return {thin.core.workspace.CustomFontRegistry} + */ +thin.core.Workspace.prototype.getCustomFonts = function () { + return this.customFonts_; +}; + + /** * @return {boolean} */ @@ -611,9 +628,16 @@ thin.core.Workspace.prototype.setFormat = function(format) { thin.core.Workspace.prototype.getSaveFormat_ = function() { var layout = this.layout_; var format = this.format; + format.setItems(layout.asJSON()); format.setLayoutGuides(layout.getHelpers().getLayoutGuideHelper().getGuides()); + format.setCustomFonts( + goog.array.map(layout.getUsedCustomFonts(), function (font) { + return font.getFamily(); + }) + ); + return format.toJSON(); }; @@ -1044,13 +1068,20 @@ thin.core.Workspace.prototype.focusElement = function(e) { var scrollTarget = this.getParent().getParent().getContentElement(); var captureLeft = scrollTarget.scrollLeft; - this.element_.focus(); + this.focus(); + var currentLeft = scrollTarget.scrollLeft; if(captureLeft != currentLeft){ scrollTarget.scrollLeft = captureLeft; } }; + +thin.core.Workspace.prototype.focus = function () { + this.element_.focus(); +}; + + /** @inheritDoc */ thin.core.Workspace.prototype.disposeInternal = function() { this.format.dispose(); @@ -1060,6 +1091,7 @@ thin.core.Workspace.prototype.disposeInternal = function() { delete this.file_; } + this.customFonts_.dispose(); this.action_.dispose(); this.history_.dispose(); @@ -1067,6 +1099,7 @@ thin.core.Workspace.prototype.disposeInternal = function() { delete this.action_; delete this.history_; delete this.layout_; + delete this.customFonts_; goog.base(this, 'disposeInternal'); }; diff --git a/app/editor/i18n.js b/app/editor/i18n.js index 1b5872a0..d783284c 100644 --- a/app/editor/i18n.js +++ b/app/editor/i18n.js @@ -147,11 +147,11 @@ thin.i18n.init = function() { var localeId = settings.getLocale(); if (!localeId) { - localeId = /** @type {string} */(thin.callApp('getUILocale')); + localeId = /** @type {string} */(thin.callAppMethod('getUILocale')); settings.setLocale(localeId); } - var locales = /** @type {Array} */(thin.callApp('getLocales')); + var locales = /** @type {Array} */(thin.callAppMethod('getLocales')); var locale = goog.array.find(locales, function(loc) { return loc.id == localeId; }); @@ -163,7 +163,7 @@ thin.i18n.init = function() { i18n.currentLocaleId_ = localeId; i18n.currentLocale_ = locale; - var defaultLocaleId = thin.callApp('getDefaultUILocale'); + var defaultLocaleId = thin.callAppMethod('getDefaultUILocale'); i18n.defaultLocaleId_ = defaultLocaleId; i18n.defaultLocale_ = goog.array.find(locales, function(loc) { return loc.id == defaultLocaleId; diff --git a/app/editor/layout/format.js b/app/editor/layout/format.js index 8f78ee7a..78a7c851 100644 --- a/app/editor/layout/format.js +++ b/app/editor/layout/format.js @@ -45,8 +45,9 @@ thin.layout.Format = function(opt_format) { this.isOverWritableVersion_ = thin.Compatibility.check(currentVersion, '>', formatVersion); this.version_ = formatVersion; - if (state && (guides = state['layout-guides'])) { - this.setLayoutGuides(guides); + if (state) { + this.setLayoutGuides(state['layout-guides'] || []); + this.setCustomFonts(state['custom-fonts'] || []); } } else { this.version_ = currentVersion; @@ -111,7 +112,8 @@ thin.layout.Format.prototype.toJSON = function() { "version": this.version_, "items": this.items_, "state": { - "layout-guides": this.getLayoutGuides() + "layout-guides": this.getLayoutGuides(), + "custom-fonts": this.getCustomFonts() } }; goog.object.extend(object, this.page.asJSON()); @@ -136,6 +138,22 @@ thin.layout.Format.prototype.getLayoutGuides = function() { }; +/** + * @return {Array.} + */ +thin.layout.Format.prototype.getCustomFonts = function () { + return this.state_['custom-fonts'] || []; +}; + + +/** + * @return {Array} + */ +thin.layout.Format.prototype.getCustomFonts = function () { + return this.state_['custom-fonts'] || []; +}; + + /** * @param {string} version */ @@ -160,6 +178,14 @@ thin.layout.Format.prototype.setLayoutGuides = function(guides) { }; +/** + * @param {Array.} fonts + */ +thin.layout.Format.prototype.setCustomFonts = function (fonts) { + this.state_['custom-fonts'] = fonts; +}; + + /** * @param {Object} items */ diff --git a/app/editor/thin.js b/app/editor/thin.js index c21bd545..ab77384f 100644 --- a/app/editor/thin.js +++ b/app/editor/thin.js @@ -19,13 +19,22 @@ goog.provide('thin.Error'); goog.require('goog.array'); +/** + * @param {string} propertyName + * @return {*} + */ +thin.app = function (propertyName) { + return goog.global['App'][propertyName]; +}; + + /** * Invoke a method of App defined in app.js. * @param {string} appMethodName * @return {*} */ -thin.callApp = function(appMethodName) { - return goog.global['App'][appMethodName](); +thin.callAppMethod = function(appMethodName) { + return thin.app(appMethodName).call(); }; @@ -37,7 +46,7 @@ thin.callApp = function(appMethodName) { */ thin.callAppHandler = function(handlerName, var_args) { var args = goog.array.slice(arguments, 1); - return goog.global['App']['handlers'][handlerName].apply(null, args); + return thin.app('handlers')[handlerName].apply(null, args); } diff --git a/app/editor/ui/combobox.js b/app/editor/ui/combobox.js index d703bc77..6efcdbe5 100644 --- a/app/editor/ui/combobox.js +++ b/app/editor/ui/combobox.js @@ -296,11 +296,12 @@ thin.ui.ComboBox.prototype.handleInputEditing = function(e) { /** * @param {goog.ui.ControlContent} content * @param {*=} opt_data + * @param {goog.ui.MenuItemRenderer=} opt_renderer * @constructor * @extends {thin.ui.Option} */ -thin.ui.ComboBoxItem = function(content, opt_data) { - thin.ui.Option.call(this, content, opt_data); +thin.ui.ComboBoxItem = function(content, opt_data, opt_renderer) { + thin.ui.Option.call(this, content, opt_data, opt_renderer); }; goog.inherits(thin.ui.ComboBoxItem, thin.ui.Option); @@ -328,4 +329,4 @@ thin.ui.ComboBoxItem.prototype.setSticky = function(sticky) { */ thin.ui.ComboBoxItem.prototype.isSticky = function() { return this.isSticky_; -}; \ No newline at end of file +}; diff --git a/app/editor/ui/fontselect.js b/app/editor/ui/fontselect.js index 97bd750d..22355727 100644 --- a/app/editor/ui/fontselect.js +++ b/app/editor/ui/fontselect.js @@ -14,38 +14,65 @@ // along with this program. If not, see . goog.provide('thin.ui.FontSelect'); -goog.provide('thin.ui.FontSelectOption'); goog.provide('thin.ui.FontOptionMenuRenderer'); +goog.provide('thin.ui.FontSelectItem'); goog.require('goog.array'); goog.require('goog.style'); -goog.require('goog.ui.ControlRenderer'); -goog.require('goog.ui.MenuItemRenderer'); -goog.require('goog.ui.MenuSeparator'); goog.require('thin.Font'); -goog.require('thin.ui.Select'); -goog.require('thin.ui.Option'); +goog.require('thin.platform.FontValidator'); + +goog.require('thin.ui.ComboBox'); +goog.require('thin.ui.ComboBoxItem'); + goog.require('thin.ui.OptionMenu'); goog.require('thin.ui.OptionMenuRenderer'); +goog.require('thin.ui.MenuSeparator'); + +goog.require('thin.ui.Input.Validator'); /** * @param {Array.} fonts - * @param {thin.ui.MenuButtonRenderer=} opt_renderer * @param {!thin.ui.FontOptionMenuRenderer=} opt_menuRenderer * @constructor - * @extends {thin.ui.Select} + * @extends {thin.ui.ComboBox} */ -thin.ui.FontSelect = function(fonts, opt_renderer, opt_menuRenderer) { +thin.ui.FontSelect = function(fonts, opt_menuRenderer) { var menu = new thin.ui.OptionMenu( opt_menuRenderer || thin.ui.FontOptionMenuRenderer.getInstance()); - goog.base(this, '', menu, opt_renderer); - - this.addFonts(fonts); + goog.base(this, menu); + + this.loadFonts_(); this.setValue(thin.Font.getDefaultFontFamily()); this.setTextAlignLeft(); + + this.initValidator_(); +}; +goog.inherits(thin.ui.FontSelect, thin.ui.ComboBox); + + +thin.ui.FontSelect.prototype.initValidator_ = function () { + var fontValidator = new thin.ui.Input.Validator(this); + + fontValidator.setAllowBlank(false); + fontValidator.setMethod(function (fontFamily) { + fontValidator.setMessage(thin.t('error_family_is_not_a_valid_font', {'family': fontFamily})); + + var workspace = thin.core.getActiveWorkspace(); + + if (workspace.getCustomFonts().contains(fontFamily)) { + return true; + } + if (thin.platform.FontValidator.validate(fontFamily)) { + return true; + } + + return false; + }); + + this.getInput().setValidator(fontValidator); }; -goog.inherits(thin.ui.FontSelect, thin.ui.Select); /** @inheritDoc */ @@ -54,64 +81,87 @@ thin.ui.FontSelect.prototype.setValue = function(name) { }; -/** - * @param {Array.} fonts - */ -thin.ui.FontSelect.prototype.addFonts = function(fonts) { - var family; - - goog.array.forEach(fonts, function(font) { - family = font.getFamily(); - if (family == 'IPAMincho') { - this.addItem(new goog.ui.MenuSeparator()); - } - this.addBuiltinFont(family, font.getName()); - }, this); +thin.ui.FontSelect.prototype.reloadFonts = function () { + this.getMenu().removeChildren(true); + this.loadFonts_(); }; /** * @param {string} family - * @param {string} name + * @private */ -thin.ui.FontSelect.prototype.addBuiltinFont = function(family, name) { - this.addFont(thin.ui.FontSelectOption.Type.BUILTIN, family, name); +thin.ui.FontSelect.prototype.registerCustomFont_ = function (family) { + var customFontRegistry = thin.core.getActiveWorkspace().getCustomFonts(); + + if (!customFontRegistry.contains(family)) { + customFontRegistry.register(family); + } }; /** - * @param {thin.ui.FontSelectOption.Type} type - * @param {string} family - * @param {string} name + * @private */ -thin.ui.FontSelect.prototype.addFont = function(type, family, name) { - this.addItem(new thin.ui.FontSelectOption(type, family, name)); +thin.ui.FontSelect.prototype.loadFonts_ = function () { + var workspace, customFonts; + + goog.array.forEach(thin.Font.getBuiltinFonts(), + function(font) { + this.addFont_(font); + }, this); + + workspace = thin.core.getActiveWorkspace(); + + if (workspace) { + customFonts = workspace.getCustomFonts().get(); + + if (!goog.array.isEmpty(customFonts)) { + this.addItem(new thin.ui.MenuSeparator()); + + goog.array.forEach(customFonts, + function (font) { + this.addFont_(font, !font.isValid()); + }, this); + } + } }; /** - * @param {thin.ui.FontSelectOption.Type} type - * @param {string} family - * @param {goog.ui.ControlContent} name - * @constructor - * @extends {thin.ui.Option} + * @param {thin.Font} font + * @param {boolean=} opt_invalid + * @private */ -thin.ui.FontSelectOption = function(type, family, name) { - var renderer = goog.ui.ControlRenderer.getCustomRenderer( - goog.ui.MenuItemRenderer, thin.ui.getCssName('thin-font-option')); - goog.base(this, name, family, - /** @type {goog.ui.MenuItemRenderer} */ (renderer)); - - this.addClassName(thin.ui.getCssName(type, 'font')); +thin.ui.FontSelect.prototype.addFont_ = function(font, opt_invalid) { + var item = new thin.ui.FontSelectItem(font, opt_invalid); + item.setSticky(true); + + this.addItem(item); +}; + + +/** @override */ +thin.ui.FontSelect.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + var handler = this.getHandler(); + + handler.listen(this.getInput(), goog.ui.Component.EventType.CHANGE, + function (e) { + this.registerCustomFont_(this.getValue()); + }, false, this); }; -goog.inherits(thin.ui.FontSelectOption, thin.ui.Option); /** - * @enum {string} + * @override */ -thin.ui.FontSelectOption.Type = { - BUILTIN: 'builtin' +thin.ui.FontSelect.prototype.showMenu_ = function () { + // Reload fonts before menu shown + this.reloadFonts(); + + goog.base(this, 'showMenu_'); }; @@ -137,3 +187,45 @@ thin.ui.FontOptionMenuRenderer.CSS_CLASS = thin.ui.FontOptionMenuRenderer.prototype.getCssClass = function() { return thin.ui.FontOptionMenuRenderer.CSS_CLASS; }; + + + +/** + * @param {thin.Font} font + * @param {boolean=} opt_invalid + * @constructor + * @extends {thin.ui.ComboBoxItem} + */ +thin.ui.FontSelectItem = function (font, opt_invalid) { + var renderer = goog.ui.ControlRenderer.getCustomRenderer( + goog.ui.MenuItemRenderer, thin.ui.getCssName(thin.ui.FontSelectItem.CSS_CLASS)); + + goog.base(this, font.getFamily(), null, /** @type {goog.ui.MenuItemRenderer} */(renderer)); + + /** + * @type {boolean?} + * @private + */ + this.invalid_ = opt_invalid; + + if (this.invalid_) { + this.addClassName(thin.ui.getCssName(thin.ui.FontSelectItem.CSS_CLASS, 'invalid')); + } +}; +goog.inherits(thin.ui.FontSelectItem, thin.ui.ComboBoxItem); + + +/** + * @type {string} + */ +thin.ui.FontSelectItem.CSS_CLASS = thin.ui.getCssName('thin-font-option'); + + +/** @override */ +thin.ui.FontSelectItem.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + if (this.invalid_) { + this.getElement().setAttribute('title', thin.t('warning_unavailable_font_not_installed', { family: this.getContent() })); + } +}; diff --git a/app/editor/ui/propertypane.js b/app/editor/ui/propertypane.js index 1c9b8bc0..0e0825a9 100644 --- a/app/editor/ui/propertypane.js +++ b/app/editor/ui/propertypane.js @@ -40,7 +40,6 @@ goog.require('goog.ui.Component.State'); goog.require('goog.ui.Component.EventType'); goog.require('goog.ui.Checkbox'); goog.require('goog.ui.Checkbox.State'); -goog.require('thin.Font'); goog.require('thin.ui.Component'); goog.require('thin.ui.Select'); goog.require('thin.ui.ComboBox'); @@ -104,7 +103,7 @@ thin.ui.PropertyPane.prototype.delay_; thin.ui.PropertyPane.prototype.createDom = function() { this.setElementInternal( this.getDomHelper().createDom('div', thin.ui.PropertyPane.CSS_CLASS)); - + goog.dom.setFocusableTabIndex(this.getElement(), true); }; @@ -130,10 +129,10 @@ thin.ui.PropertyPane.prototype.addProperty = function(property, group, opt_id) { */ thin.ui.PropertyPane.prototype.addItem = function(item, opt_id) { this.addChildWithId(item, opt_id, true); - - item.addEventListener(thin.ui.PropertyPane.AbstractItem.EventType.TARGETTING, + + item.addEventListener(thin.ui.PropertyPane.AbstractItem.EventType.TARGETTING, this.handleItemTargetting, true, this); - + if (this.selectionModel_) { this.selectionModel_.addItem(item); } else { @@ -173,7 +172,7 @@ thin.ui.PropertyPane.prototype.hasActiveControlItem = function() { * @param {goog.events.Event} e */ thin.ui.PropertyPane.prototype.handleWatchItemActivate = function(e) { - + }; @@ -201,7 +200,7 @@ thin.ui.PropertyPane.prototype.setTargettedItem = function(item) { * @return {thin.ui.PropertyPane.AbstractItem?} */ thin.ui.PropertyPane.prototype.getTargettedItem = function() { - return this.selectionModel_ ? + return this.selectionModel_ ? /** @type {thin.ui.PropertyPane.AbstractItem} */ (this.selectionModel_.getSelectedItem()) : null; @@ -217,7 +216,7 @@ thin.ui.PropertyPane.prototype.createSelectionModel_ = function() { model.addItem(child); }, this); this.selectionModel_ = model; - + model.setSelectionHandler(function(item, select) { if (item.canTargetting()) { item.setTargettedInternal(select); @@ -262,7 +261,7 @@ thin.ui.PropertyPane.prototype.getTarget = function() { thin.ui.PropertyPane.prototype.isTarget = function(target) { var currentTarget = this.target_; if (currentTarget && target) { - return goog.getUid(/** @type {Object} */ (currentTarget)) == + return goog.getUid(/** @type {Object} */ (currentTarget)) == goog.getUid(/** @type {Object} */ (target)); } return false; @@ -273,7 +272,7 @@ thin.ui.PropertyPane.prototype.clear = function() { while (this.hasChildren()) { this.removeChildAt(0, true).dispose(); } - + this.selectionModel_ && this.selectionModel_.clear(); this.target_ = null; }; @@ -284,7 +283,7 @@ thin.ui.PropertyPane.prototype.clear = function() { * @return {boolean} */ thin.ui.PropertyPane.prototype.handleKeyEvent = function(e) { - if (!this.hasActiveControlItem() && + if (!this.hasActiveControlItem() && this.getChildCount() != 0 && this.handleKeyEventInternal(e)) { e.preventDefault(); @@ -304,25 +303,25 @@ thin.ui.PropertyPane.prototype.handleKeyEventInternal = function(e) { case goog.events.KeyCodes.UP: this.changeTargetBy_(-1); break; - + case goog.events.KeyCodes.DOWN: this.changeTargetBy_(+1); break; - + case goog.events.KeyCodes.TAB: this.changeTargetBy_(e.shiftKey ? -1 : +1); break; - + case goog.events.KeyCodes.F2: case goog.events.KeyCodes.SPACE: this.handlePropertyActivateControl(e); break; - + default: return false; break; } - + return true; }; @@ -356,14 +355,14 @@ thin.ui.PropertyPane.prototype.changeTargetBy_ = function(mode) { } } else { nextItem = mode == -1 ? model.getLast() : model.getFirst(); - } + } this.setTargettedItem(/** @type {thin.ui.PropertyPane.AbstractItem} */ (nextItem)); - + if (!nextItem.canTargetting()) { this.changeTargetBy_(mode); return; } - + nextItem.getElement().focus(); } }; @@ -381,29 +380,29 @@ thin.ui.PropertyPane.prototype.getKeyHandler = function() { /** @inheritDoc */ thin.ui.PropertyPane.prototype.disposeInternal = function(){ thin.ui.PropertyPane.superClass_.disposeInternal.call(this); - + if (this.keyHandler_) { this.keyHandler_.dispose(); delete this.keyHandler_; } - + if (this.delay_) { this.delay_.dispose(); this.delay_ = null; } - + if (this.selectionModel_) { this.selectionModel_.dispose(); delete this.selectionModel_; } - + delete this.target_; }; thin.ui.PropertyPane.prototype.enterDocument = function() { thin.ui.PropertyPane.superClass_.enterDocument.call(this); - + this.getHandler(). listen(this.getKeyHandler(), goog.events.KeyHandler.EventType.KEY, this.handleKeyEvent, false, this); @@ -418,10 +417,10 @@ thin.ui.PropertyPane.prototype.enterDocument = function() { */ thin.ui.PropertyPane.AbstractItem = function(content, opt_renderer) { goog.ui.Control.call(this, content, opt_renderer); - + this.setSupportedState(goog.ui.Component.State.HOVER, false); this.setSupportedState(goog.ui.Component.State.ACTIVE, false); - + this.setHandleMouseEvents(false); }; goog.inherits(thin.ui.PropertyPane.AbstractItem, goog.ui.Control); @@ -496,7 +495,7 @@ thin.ui.PropertyPane.AbstractItem.prototype.setTargettedInternal = function(targ this.targetted_ = false; } - goog.dom.classes.enable(this.getElement(), + goog.dom.classes.enable(this.getElement(), thin.ui.getCssName(this.getRenderer().getCssClass(), 'target'), targetted); }; @@ -521,9 +520,9 @@ thin.ui.PropertyPane.AbstractItem.prototype.handleFocus = function(e) { thin.ui.PropertyPane.AbstractItem.prototype.enterDocument = function() { thin.ui.PropertyPane.AbstractItem.superClass_.enterDocument.call(this); - + this.getHandler(). - listen(this.getElement(), goog.events.EventType.FOCUS, + listen(this.getElement(), goog.events.EventType.FOCUS, this.handleFocus, false, this); }; @@ -534,14 +533,14 @@ thin.ui.PropertyPane.AbstractItem.prototype.enterDocument = function() { * @extends {thin.ui.PropertyPane.AbstractItem} */ thin.ui.PropertyPane.PropertyGroup = function(label) { - thin.ui.PropertyPane.AbstractItem.call(this, label, + thin.ui.PropertyPane.AbstractItem.call(this, label, goog.ui.ControlRenderer.getCustomRenderer( goog.ui.ControlRenderer, thin.ui.getCssName( thin.ui.PropertyPane.CSS_CLASS, 'group'))); - + this.setSupportedState(goog.ui.Component.State.OPENED, true); this.setOpen(true); - + /** * @type {Array.} * @private @@ -569,9 +568,9 @@ thin.ui.PropertyPane.PropertyGroup.prototype.removeMember = function(property) { thin.ui.PropertyPane.PropertyGroup.prototype.enterDocument = function() { thin.ui.PropertyPane.PropertyGroup.superClass_.enterDocument.call(this); - + this.getHandler(). - listen(this.getElement(), goog.events.EventType.DBLCLICK, + listen(this.getElement(), goog.events.EventType.DBLCLICK, this.handleDblClickOrSpace_, false, this); }; @@ -579,7 +578,7 @@ thin.ui.PropertyPane.PropertyGroup.prototype.enterDocument = function() { /** @inheritDoc */ thin.ui.PropertyPane.PropertyGroup.prototype.disposeInternal = function() { thin.ui.PropertyPane.PropertyGroup.superClass_.disposeInternal.call(this); - + delete this.member_; }; @@ -615,15 +614,15 @@ thin.ui.PropertyPane.PropertyGroup.prototype.handleDblClickOrSpace_ = function(e * @extends {thin.ui.PropertyPane.AbstractItem} */ thin.ui.PropertyPane.Property = function(label, control) { - thin.ui.PropertyPane.AbstractItem.call(this, label, + thin.ui.PropertyPane.AbstractItem.call(this, label, thin.ui.PropertyPane.PropertyRenderer.getInstance()); - + /** * @type {thin.ui.PropertyPane.Property.Key_} * @private */ this.keyControl_ = new thin.ui.PropertyPane.Property.Key_(label); - + /** * @type {thin.ui.PropertyPane.Property.Value_} * @private @@ -637,8 +636,8 @@ goog.inherits(thin.ui.PropertyPane.Property, thin.ui.PropertyPane.AbstractItem); * @enum {string} */ thin.ui.PropertyPane.Property.EventType = { - ACTIVE: 'active', - INACTIVE: 'inactive', + ACTIVE: 'active', + INACTIVE: 'inactive', CHANGE: 'propchange' }; @@ -681,7 +680,7 @@ thin.ui.PropertyPane.Property.prototype.getValueControl = function() { /** @inheritDoc */ thin.ui.PropertyPane.Property.prototype.createDom = function() { thin.ui.PropertyPane.Property.superClass_.createDom.call(this); - + this.addChild(this.keyControl_, true); this.addChild(this.valueCell_, true); }; @@ -711,7 +710,7 @@ thin.ui.PropertyPane.Property.prototype.setGroup = function(group) { * @param {boolean} enable */ thin.ui.PropertyPane.Property.prototype.setEnabled = function(enable) { - thin.ui.PropertyPane.Property.superClass_.setEnabled.call(this, enable); + thin.ui.PropertyPane.Property.superClass_.setEnabled.call(this, enable); this.getValueControl().setEnabled(enable); }; @@ -750,7 +749,7 @@ thin.ui.PropertyPane.Property.prototype.setControlActive = function(active) { } else { this.getParent().setActiveControlItem(null); this.getElement().focus(); - this.dispatchEvent(thin.ui.PropertyPane.Property.EventType.INACTIVE); + this.dispatchEvent(thin.ui.PropertyPane.Property.EventType.INACTIVE); } }; @@ -787,8 +786,8 @@ thin.ui.PropertyPane.Property.prototype.inactivateControlInternal = function() { thin.ui.PropertyPane.Property.prototype.dispatchPropertyChangeEvent = function() { this.dispatchEvent( new thin.ui.PropertyPane.PropertyEvent( - thin.ui.PropertyPane.Property.EventType.CHANGE, - /** @type {thin.ui.PropertyPane} */ (this.getParent()), + thin.ui.PropertyPane.Property.EventType.CHANGE, + /** @type {thin.ui.PropertyPane} */ (this.getParent()), this, this.getValueControl())); }; @@ -826,7 +825,7 @@ goog.addSingletonGetter(thin.ui.PropertyPane.PropertyRenderer); /** * @type {string} */ -thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS = +thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS = thin.ui.getCssName(thin.ui.PropertyPane.CSS_CLASS, 'prop'); @@ -841,7 +840,7 @@ thin.ui.PropertyPane.PropertyRenderer.prototype.getCssClass = function() { /** @inheritDoc */ thin.ui.PropertyPane.PropertyRenderer.prototype.createDom = function(prop) { var domHelper = prop.getDomHelper(); - return domHelper.createDom('div', this.getClassNames(prop).join(' '), + return domHelper.createDom('div', this.getClassNames(prop).join(' '), domHelper.createDom('div', thin.ui.getCssName(this.getCssClass(), 'body'))); }; @@ -862,7 +861,7 @@ thin.ui.PropertyPane.PropertyRenderer.prototype.getContentElement = function(ele */ thin.ui.PropertyPane.Property.Key_ = function(label) { goog.ui.Component.call(this); - + /** * @type {string} * @private @@ -875,8 +874,8 @@ goog.inherits(thin.ui.PropertyPane.Property.Key_, goog.ui.Component); /** @inheritDoc */ thin.ui.PropertyPane.Property.Key_.prototype.createDom = function() { thin.ui.PropertyPane.Property.Key_.superClass_.createDom.call(this); - - goog.dom.classes.add(this.getElement(), + + goog.dom.classes.add(this.getElement(), thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS + 'key')); this.setLabel(this.label_); @@ -932,10 +931,10 @@ thin.ui.PropertyPane.Property.Value_.prototype.getControl = function() { /** @inheritDoc */ thin.ui.PropertyPane.Property.Value_.prototype.createDom = function() { thin.ui.PropertyPane.Property.Value_.superClass_.createDom.call(this); - - goog.dom.classes.add(this.getElement(), + + goog.dom.classes.add(this.getElement(), thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS + 'value')); - + this.addChild(this.control_, true); }; @@ -943,7 +942,7 @@ thin.ui.PropertyPane.Property.Value_.prototype.createDom = function() { /** @inheritDoc */ thin.ui.PropertyPane.Property.Value_.prototype.disposeInternal = function() { thin.ui.PropertyPane.Property.Value_.superClass_.disposeInternal.call(this); - + this.control_ = null; }; @@ -956,17 +955,17 @@ thin.ui.PropertyPane.Property.Value_.prototype.disposeInternal = function() { */ thin.ui.PropertyPane.SelectProperty = function(label, opt_menu) { var renderer = goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.MenuButtonRenderer, + thin.ui.MenuButtonRenderer, thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'select')); - + var menuRenderer = goog.ui.ControlRenderer.getCustomRenderer( thin.ui.OptionMenuRenderer, thin.ui.getCssName(renderer.getCssClass(), 'optionmenu')); - var control = new thin.ui.Select(undefined, new thin.ui.OptionMenu(menuRenderer), + var control = new thin.ui.Select(undefined, new thin.ui.OptionMenu(menuRenderer), /** @type {thin.ui.MenuButtonRenderer} */ (renderer)); - + control.getMenu().setMaxHeight(200); - + thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.SelectProperty, thin.ui.PropertyPane.Property); @@ -986,7 +985,7 @@ thin.ui.PropertyPane.SelectProperty.prototype.handleInactivate = function(e){ thin.ui.PropertyPane.SelectProperty.prototype.activateControlInternal = function() { this.getValueControl().setOpen(true); this.getValueControl().getElement().focus(); - + return true; }; @@ -994,44 +993,20 @@ thin.ui.PropertyPane.SelectProperty.prototype.activateControlInternal = function /** @inheritDoc */ thin.ui.PropertyPane.SelectProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.SelectProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.ACTION, this.dispatchPropertyChangeEvent, false, this); - + // For Inactive control.getMenu(). - addEventListener(goog.ui.Component.EventType.HIDE, + addEventListener(goog.ui.Component.EventType.HIDE, this.handleInactivate, false, this); }; -/** - * @param {string=} opt_label - * @constructor - * @extends {thin.ui.PropertyPane.SelectProperty} - */ -thin.ui.PropertyPane.FontSelectProperty = function(opt_label) { - var propCssClass = thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS; - - var renderer = goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.MenuButtonRenderer, thin.ui.getCssName(propCssClass, 'select')); - var menuRenderer = goog.ui.ContainerRenderer.getCustomRenderer( - thin.ui.FontOptionMenuRenderer, thin.ui.getCssName(propCssClass, 'font-selectmenu')); - - var control = new thin.ui.FontSelect(thin.Font.getFonts(), - /** @type {thin.ui.MenuButtonRenderer} */ (renderer), - /** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); - - control.getMenu().setMaxHeight(250); - - thin.ui.PropertyPane.Property.call(this, opt_label || thin.t('field_font_family'), control); -}; -goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.SelectProperty); - - /** * @param {string} label * @param {goog.ui.Component=} opt_control @@ -1040,9 +1015,9 @@ goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.Sele * @constructor */ thin.ui.PropertyPane.AbstractCheckableProperty = function(label, opt_control, opt_checked) { - var control = new goog.ui.Control(null, + var control = new goog.ui.Control(null, goog.ui.ControlRenderer.getCustomRenderer( - goog.ui.ControlRenderer, + goog.ui.ControlRenderer, thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'checkable-ctl'))); control.setSupportedState(goog.ui.Component.State.HOVER, false); @@ -1112,11 +1087,11 @@ thin.ui.PropertyPane.AbstractCheckableProperty.prototype.handleInactivate = func /** @inheritDoc */ thin.ui.PropertyPane.AbstractCheckableProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.AbstractCheckableProperty.superClass_.enterDocument.call(this); - - // For Inactive by Checkbox. - this.getValueControlCheckbox().addEventListener(goog.ui.Component.EventType.CHANGE, + + // For Inactive by Checkbox. + this.getValueControlCheckbox().addEventListener(goog.ui.Component.EventType.CHANGE, this.handleInactivate, true, this); - + // For Common-Change by Checkbox. this.getValueControl().addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); @@ -1135,7 +1110,7 @@ thin.ui.PropertyPane.CheckableInputProperty = function(label, opt_label, opt_che thin.ui.PropertyPane.AbstractCheckableProperty.call(this, label, control, opt_checked); }; -goog.inherits(thin.ui.PropertyPane.CheckableInputProperty, +goog.inherits(thin.ui.PropertyPane.CheckableInputProperty, thin.ui.PropertyPane.AbstractCheckableProperty); @@ -1148,7 +1123,7 @@ thin.ui.PropertyPane.CheckableInputProperty.prototype.activateControlInternal = this.getValueControlCheckbox().dispatchEvent( goog.ui.Component.EventType.CHANGE); } - + goog.dom.forms.focusAndSelect(this.getValueControlMain().getElement()); return true; @@ -1195,22 +1170,22 @@ thin.ui.PropertyPane.CheckableInputProperty.prototype.handleClickInput = functio /** @inheritDoc */ thin.ui.PropertyPane.CheckableInputProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.CheckableInputProperty.superClass_.enterDocument.call(this); - + var inputControl = this.getValueControlMain(); - + // For Common-Change by Input(MainControl). inputControl.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Inactive by Input(MainControl). - goog.events.listen(inputControl, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(inputControl, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active by Input(MainControl). goog.events.listen(inputControl.getElement(), goog.events.EventType.CLICK, this.handleClickInput, false, this); - + // For Click Active by Checkbox(CheckboxControl). goog.events.listen(this.getValueControlCheckbox().getElement(), goog.events.EventType.CLICK, this.handleClickCheck, false, this); @@ -1243,7 +1218,7 @@ thin.ui.PropertyPane.InputProperty.prototype.handleInactivate = function(e){ */ thin.ui.PropertyPane.InputProperty.prototype.activateControlInternal = function() { goog.dom.forms.focusAndSelect(this.getValueControl().getElement()); - + return true; }; @@ -1251,18 +1226,18 @@ thin.ui.PropertyPane.InputProperty.prototype.activateControlInternal = function( /** @inheritDoc */ thin.ui.PropertyPane.InputProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.InputProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Active/Inactive - goog.events.listen(control, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1301,18 +1276,18 @@ thin.ui.PropertyPane.NumberInputProperty.prototype.activateControlInternal = fun /** @inheritDoc */ thin.ui.PropertyPane.NumberInputProperty.prototype.enterDocument = function() { goog.base(this, 'enterDocument'); - + var control = this.getValueControl().getInput(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Active/Inactive - goog.events.listen(control, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1328,12 +1303,12 @@ thin.ui.PropertyPane.NumberInputProperty.prototype.enterDocument = function() { */ thin.ui.PropertyPane.IdInputProperty = function(target, label, opt_label) { goog.base(this, label, opt_label); - + var control = this.getValueControl(); var validator = new thin.ui.PropertyPane.IdInputProperty.Validator_(control); validator.setShape(target); control.setValidator(validator); - + /** * @type {thin.ui.PropertyPane.IdInputProperty.Validator_} * @private @@ -1355,7 +1330,7 @@ thin.ui.PropertyPane.IdInputProperty.prototype.getIdValidator = function() { /** @inheritDoc */ thin.ui.PropertyPane.IdInputProperty.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); - + delete this.idValidator_; }; @@ -1367,7 +1342,7 @@ thin.ui.PropertyPane.IdInputProperty.prototype.disposeInternal = function() { */ thin.ui.PropertyPane.IdInputProperty.Validator_ = function(opt_target) { goog.base(this, opt_target); - + this.setValidatePresence(this.validatePresence_); this.setMethod(this.validate_); }; @@ -1452,7 +1427,7 @@ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.validate_ = function(v /** @inheritDoc */ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.disposeInternal = function() { goog.base(this, 'disposeInternal'); - + this.shape_ = null; }; @@ -1460,17 +1435,39 @@ thin.ui.PropertyPane.IdInputProperty.Validator_.prototype.disposeInternal = func /** * @param {string} label * @param {thin.ui.OptionMenu=} opt_menu + * @param {thin.ui.ComboBox=} opt_control * @constructor * @extends {thin.ui.PropertyPane.Property} */ -thin.ui.PropertyPane.ComboBoxProperty = function(label, opt_menu) { - var control = thin.ui.ComboBox.getCustomComboBox( - thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'combobox'), opt_menu); - +thin.ui.PropertyPane.ComboBoxProperty = function(label, opt_menu, opt_control) { + var cssClass = thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'combobox'); + var control; + + if (opt_control) { + control = thin.ui.PropertyPane.ComboBoxProperty.buildCustomControl(cssClass, opt_control); + } else { + control = thin.ui.ComboBox.getCustomComboBox(cssClass, opt_menu); + } + thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.ComboBoxProperty, thin.ui.PropertyPane.Property); +/** + * @param {string} cssClass + * @param {thin.ui.ComboBox} control + * @return {thin.ui.ComboBox} + */ +thin.ui.PropertyPane.ComboBoxProperty.buildCustomControl = function (cssClass, control) { + /** + * @return {string} + */ + control.getCssClass = function () { + return cssClass; + } + return control; +}; + /** * @param {goog.events.Event} e @@ -1497,7 +1494,7 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.activateControlInternal = functi /** @inheritDoc */ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.ComboBoxProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); // For Common-Change @@ -1505,16 +1502,36 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); // For Active/Inactive - goog.events.listen(control.getInput(), - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control.getInput(), + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getInput().getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); }; +/** + * @param {string=} opt_label + * @constructor + * @extends {thin.ui.PropertyPane.ComboBoxProperty} + */ +thin.ui.PropertyPane.FontSelectProperty = function(opt_label) { + var propCssClass = thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS; + + var menuRenderer = goog.ui.ContainerRenderer.getCustomRenderer( + thin.ui.FontOptionMenuRenderer, thin.ui.getCssName(propCssClass, 'font-selectmenu')); + + var control = new thin.ui.FontSelect(/** @type {thin.ui.FontOptionMenuRenderer} */ (menuRenderer)); + + control.getMenu().setMaxHeight(250); + + goog.base(this, opt_label || thin.t('field_font_family'), null, control); +}; +goog.inherits(thin.ui.PropertyPane.FontSelectProperty, thin.ui.PropertyPane.ComboBoxProperty); + + /** * @param {string} label * @param {string=} opt_label @@ -1525,7 +1542,7 @@ thin.ui.PropertyPane.ComboBoxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.CheckboxProperty = function(label, opt_label, opt_checked) { var control = new thin.ui.Checkbox(opt_label || '', opt_checked); control.setSupportedState(goog.ui.Component.State.FOCUSED, false); - + thin.ui.PropertyPane.Property.call(this, label, control); }; goog.inherits(thin.ui.PropertyPane.CheckboxProperty, thin.ui.PropertyPane.Property); @@ -1537,7 +1554,7 @@ goog.inherits(thin.ui.PropertyPane.CheckboxProperty, thin.ui.PropertyPane.Proper thin.ui.PropertyPane.CheckboxProperty.prototype.activateControlInternal = function() { this.getValueControl().toggle(); this.dispatchPropertyChangeEvent(); - + return false; }; @@ -1558,7 +1575,7 @@ thin.ui.PropertyPane.CheckboxProperty.prototype.handleClick = function(e) { /** @inheritDoc */ thin.ui.PropertyPane.CheckboxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.CheckboxProperty.superClass_.enterDocument.call(this); - + // For Click Active and Common-Change goog.events.listen(this.getValueControl().getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); @@ -1573,7 +1590,7 @@ thin.ui.PropertyPane.CheckboxProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.ColorProperty = function(label) { var control = new thin.ui.InputColorPicker( /** @type {thin.ui.InputColorPickerRenderer} */ ( - goog.ui.ControlRenderer.getCustomRenderer(thin.ui.InputColorPickerRenderer, + goog.ui.ControlRenderer.getCustomRenderer(thin.ui.InputColorPickerRenderer, thin.ui.getCssName(thin.ui.PropertyPane.PropertyRenderer.CSS_CLASS, 'color')))); thin.ui.PropertyPane.Property.call(this, label, control); @@ -1603,33 +1620,33 @@ thin.ui.PropertyPane.ColorProperty.prototype.handleInactivate = function(e) { /** @inheritDoc */ thin.ui.PropertyPane.ColorProperty.prototype.enterDocument = function() { thin.ui.PropertyPane.ColorProperty.superClass_.enterDocument.call(this); - + var control = this.getValueControl(); - + // For Common-Change control.addEventListener( goog.ui.Component.EventType.CHANGE, this.dispatchPropertyChangeEvent, false, this); - + // For Active/Inactive control.addEventListener( goog.ui.Component.EventType.ACTION, this.handleInactivate, false, this); - goog.events.listen(control, - [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + goog.events.listen(control, + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], this.handleInactivate, false, this); var colorMenuButton = control.getButton(); var colorMenu = colorMenuButton.getMenu(); colorMenu. - addEventListener(goog.ui.Component.EventType.SHOW, + addEventListener(goog.ui.Component.EventType.SHOW, function(e) { if(!colorMenuButton.isFocused()) { colorMenuButton.getElement().focus(); } }, false, this); colorMenu. - addEventListener(goog.ui.Component.EventType.HIDE, + addEventListener(goog.ui.Component.EventType.HIDE, this.handleInactivate, false, this); - + // For Click Active goog.events.listen(control.getInput().getElement(), goog.events.EventType.CLICK, this.handleClick, false, this); diff --git a/app/editor/ui/toolbar.js b/app/editor/ui/toolbar.js index d9f8dba1..a9c5fc3e 100644 --- a/app/editor/ui/toolbar.js +++ b/app/editor/ui/toolbar.js @@ -30,7 +30,6 @@ goog.require('goog.array'); goog.require('goog.ui.Component.EventType'); goog.require('goog.ui.Separator'); goog.require('goog.ui.ControlRenderer'); -goog.require('thin.Font'); goog.require('thin.ui.Component'); goog.require('thin.ui.Button'); goog.require('thin.ui.ButtonRenderer'); @@ -72,7 +71,7 @@ thin.ui.Toolbar.CSS_CLASS = thin.ui.getCssName('thin-toolbar'); thin.ui.Toolbar.prototype.setupChild = function(id, child, renderTo, opt_setupHandler) { thin.ui.Toolbar.superClass_.setupChild.call(this, child, id, opt_setupHandler, false); child.render(renderTo); - + return child; }; @@ -85,7 +84,7 @@ thin.ui.Toolbar.prototype.setupChild = function(id, child, renderTo, opt_setupHa * @extends {thin.ui.Button} */ thin.ui.ToolbarButton = function(content, opt_icon, opt_renderer) { - thin.ui.Button.call(this, content, opt_icon, + thin.ui.Button.call(this, content, opt_icon, /** @type {thin.ui.ButtonRenderer} */ (opt_renderer || goog.ui.ControlRenderer.getCustomRenderer( thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); @@ -101,10 +100,10 @@ goog.inherits(thin.ui.ToolbarButton, thin.ui.Button); * @extends {thin.ui.ToggleButton} */ thin.ui.ToolbarToggleButton = function(content, opt_icon, opt_renderer) { - thin.ui.ToggleButton.call(this, content, opt_icon, - /** @type {thin.ui.ButtonRenderer} */ (opt_renderer || + thin.ui.ToggleButton.call(this, content, opt_icon, + /** @type {thin.ui.ButtonRenderer} */ (opt_renderer || goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.ButtonRenderer, + thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); }; goog.inherits(thin.ui.ToolbarToggleButton, thin.ui.ToggleButton); @@ -116,10 +115,10 @@ goog.inherits(thin.ui.ToolbarToggleButton, thin.ui.ToggleButton); * @extends {thin.ui.IconButton} */ thin.ui.ToolbarIconButton = function(icon) { - thin.ui.IconButton.call(this, icon, + thin.ui.IconButton.call(this, icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.ButtonRenderer, + thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); }; goog.inherits(thin.ui.ToolbarIconButton, thin.ui.IconButton); @@ -131,10 +130,10 @@ goog.inherits(thin.ui.ToolbarIconButton, thin.ui.IconButton); * @extends {thin.ui.ToggleIconButton} */ thin.ui.ToolbarToggleIconButton = function(icon) { - thin.ui.ToggleIconButton.call(this, icon, + thin.ui.ToggleIconButton.call(this, icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( - thin.ui.ButtonRenderer, + thin.ui.ButtonRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'button')))); }; goog.inherits(thin.ui.ToolbarToggleIconButton, thin.ui.ToggleIconButton); @@ -148,7 +147,7 @@ goog.inherits(thin.ui.ToolbarToggleIconButton, thin.ui.ToggleIconButton); * @extends {thin.ui.MenuButton} */ thin.ui.ToolbarMenuButton = function(content, opt_icon, opt_menu) { - thin.ui.MenuButton.call(this, content, opt_icon, opt_menu, + thin.ui.MenuButton.call(this, content, opt_icon, opt_menu, /** @type {thin.ui.MenuButtonRenderer} */( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.MenuButtonRenderer, thin.ui.getCssName( @@ -166,23 +165,23 @@ goog.inherits(thin.ui.ToolbarMenuButton, thin.ui.MenuButton); */ thin.ui.ToolbarSplitButton = function(content, opt_icon, opt_orientation) { var cssClass = thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'split-button'); - - thin.ui.SplitButton.call(this, content, opt_icon, opt_orientation, + + thin.ui.SplitButton.call(this, content, opt_icon, opt_orientation, /** @type {thin.ui.SplitButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.SplitButtonRenderer, thin.ui.getCssName(cssClass)))); - + /** @inheritDoc */ - this.button_ = new thin.ui.ToolbarButton(content, opt_icon, + this.button_ = new thin.ui.ToolbarButton(content, opt_icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.ButtonRenderer, thin.ui.getCssName(cssClass, 'button')))); /** @inheritDoc */ this.handle_ = new thin.ui.ToolbarSplitButton.Handle(); - + /** @inheritDoc */ - this.orientation_ = opt_orientation || + this.orientation_ = opt_orientation || thin.ui.SplitButton.Orientation.HORIZONTAL; }; goog.inherits(thin.ui.ToolbarSplitButton, thin.ui.SplitButton); @@ -193,8 +192,8 @@ goog.inherits(thin.ui.ToolbarSplitButton, thin.ui.SplitButton); * @extends {thin.ui.SplitButton.Handle} */ thin.ui.ToolbarSplitButton.Handle = function() { - thin.ui.SplitButton.Handle.call(this, - /** @type {thin.ui.SplitButtonHandleRenderer} */ ( + thin.ui.SplitButton.Handle.call(this, + /** @type {thin.ui.SplitButtonHandleRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.SplitButtonHandleRenderer, thin.ui.getCssName( thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'split-button'), 'handle')))); @@ -211,14 +210,14 @@ goog.inherits(thin.ui.ToolbarSplitButton.Handle, thin.ui.SplitButton.Handle); */ thin.ui.ToolbarSplitToggleButton = function(content, opt_icon, opt_orientation) { var cssClass = thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'split-button'); - - thin.ui.SplitToggleButton.call(this, content, opt_icon, opt_orientation, + + thin.ui.SplitToggleButton.call(this, content, opt_icon, opt_orientation, /** @type {thin.ui.SplitButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.SplitButtonRenderer, thin.ui.getCssName(cssClass)))); - + /** @inheritDoc */ - this.button_ = new thin.ui.ToolbarToggleButton(content, opt_icon, + this.button_ = new thin.ui.ToolbarToggleButton(content, opt_icon, /** @type {thin.ui.ButtonRenderer} */ ( goog.ui.ControlRenderer.getCustomRenderer( thin.ui.ButtonRenderer, thin.ui.getCssName( @@ -249,22 +248,38 @@ goog.inherits(thin.ui.ToolbarSelect, thin.ui.Select); * @extends {thin.ui.FontSelect} */ thin.ui.ToolbarFontSelect = function() { - thin.ui.FontSelect.call(this, thin.Font.getFonts()); - this.addClassName(thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'select')); + thin.ui.FontSelect.call(this); }; goog.inherits(thin.ui.ToolbarFontSelect, thin.ui.FontSelect); +/** @override */ +thin.ui.ToolbarFontSelect.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + var handler = this.getHandler(); + + handler.listen(this.getInput(), + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + function (e) { + var workspace = thin.core.getActiveWorkspace(); + if (workspace) { + workspace.focus(); + } + }, false, this); +}; + + /** * @param {goog.ui.MenuSeparatorRenderer=} opt_renderer * @constructor * @extends {goog.ui.Separator} */ thin.ui.ToolbarSeparator = function(opt_renderer) { - goog.ui.Separator.call(this, - /** @type {goog.ui.MenuSeparatorRenderer} */(opt_renderer || + goog.ui.Separator.call(this, + /** @type {goog.ui.MenuSeparatorRenderer} */(opt_renderer || goog.ui.ControlRenderer.getCustomRenderer( - goog.ui.ControlRenderer, + goog.ui.ControlRenderer, thin.ui.getCssName(thin.ui.Toolbar.CSS_CLASS, 'separator')))); }; goog.inherits(thin.ui.ToolbarSeparator, goog.ui.Separator); diff --git a/app/editor/ui/toolbar/combobox.js b/app/editor/ui/toolbar/combobox.js new file mode 100644 index 00000000..c65cfead --- /dev/null +++ b/app/editor/ui/toolbar/combobox.js @@ -0,0 +1,47 @@ +// Copyright (C) 2011 Matsukei Co.,Ltd. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +goog.provide('thin.ui.toolbar.ComboBox'); + +goog.require('thin.core'); +goog.require('thin.ui.ComboBox'); +goog.require('thin.ui.Input.EventType'); + +/** + * @param {thin.ui.OptionMenu=} opt_menu + * @constructor + * @extends {thin.ui.ComboBox} + */ +thin.ui.toolbar.ComboBox = function (opt_menu) { + goog.base(this, opt_menu); +}; +goog.inherits(thin.ui.toolbar.ComboBox, thin.ui.ComboBox); + + +/** @override */ +thin.ui.toolbar.ComboBox.prototype.enterDocument = function () { + goog.base(this, 'enterDocument'); + + var handler = this.getHandler(); + + handler.listen(this.getInput(), + [thin.ui.Input.EventType.END_EDITING, thin.ui.Input.EventType.CANCEL_EDITING], + function (e) { + var workspace = thin.core.getActiveWorkspace(); + if (workspace) { + workspace.focus(); + } + }, false, this); +}; diff --git a/app/index.html b/app/index.html index 90408c9c..35d914e6 100644 --- a/app/index.html +++ b/app/index.html @@ -272,5 +272,7 @@

Aa diff --git a/app/index.js b/app/index.js index d721cfaf..4d3225da 100644 --- a/app/index.js +++ b/app/index.js @@ -15,6 +15,7 @@ var App = {}; +App.FontMetrics = require('fontmetrics'); App.handlers = require('./handlers'); /** diff --git a/app/locales/en.js b/app/locales/en.js index 048b9985..58b86a99 100644 --- a/app/locales/en.js +++ b/app/locales/en.js @@ -212,10 +212,12 @@ App.addLocale({ error_failed_to_load_image: 'Failed to load image.', error_no_valid_placeholder_included: 'No a valid placeholder included.', error_unexpected_error: 'An unexpected error occurred.', + error_family_is_not_a_valid_font: '{$family} is not a valid font.', notice_no_shapes: 'No shapes', warning_discard_changes: 'If you have unsaved files, the changes will be discarded. Please be sure to save.', warning_discard_changes_en: '', + warning_unavailable_font_not_installed: "{$family} is not available because it won't be installed.", text_editor_force_close_confirmation: 'There are unsaved files. Are you sure you want to close without saving changes?', text_layout_force_close_confirmation: 'This layout has been changed.\nSave before close?', diff --git a/app/locales/ja.js b/app/locales/ja.js index c96a33b7..dc1f85e0 100644 --- a/app/locales/ja.js +++ b/app/locales/ja.js @@ -212,9 +212,12 @@ App.addLocale({ error_failed_to_load_image: '画像ファイルの読み込みに失敗しました。', error_no_valid_placeholder_included: '有効なプレースホルダが一つも含まれていません。', error_unexpected_error: '予期しないエラーが発生しました。', + error_family_is_not_a_valid_font: '{$family} は有効なフォントではありません。', + notice_no_shapes: 'オブジェクトはありません', warning_discard_changes: '保存していないレイアウトがある場合は必ず保存して下さい。', warning_discard_changes_en: 'If you have unsaved files, the changes will be discarded. Please be sure to save.', + warning_unavailable_font_not_installed: '{$family} は利用できません。インストールしてください。', text_editor_force_close_confirmation: '保存されていないファイルがあります。変更を保存せずに閉じても良いですか?', text_layout_force_close_confirmation: '内容が変更されています。\n保存しますか?', diff --git a/app/locales/pt-BR.js b/app/locales/pt-BR.js index 987644f2..696e9f93 100644 --- a/app/locales/pt-BR.js +++ b/app/locales/pt-BR.js @@ -212,10 +212,12 @@ App.addLocale({ error_failed_to_load_image: 'Falha ao carregar a imagem.', error_no_valid_placeholder_included: 'Sem um espaco reservado valido incluido.', error_unexpected_error: 'Ocorreu um erro inesperado.', + error_family_is_not_a_valid_font: '{$family} is not a valid font.', notice_no_shapes: 'Nao ha formas', warning_discard_changes: 'Se voce tiver arquivos que nao foram salvos, as alteracoes serao descartadas.\nPor favor, nao se esqueca de salvar.', warning_discard_changes_en: '', + warning_unavailable_font_not_installed: '{$family} não está disponível porque não será instalada.', text_editor_force_close_confirmation: 'Existem arquivos não salvos. Tem certeza de que deseja fechar sem salvar as alterações?', text_layout_force_close_confirmation: 'Este layout foi alterado. \nSalvar antes de fechar?', diff --git a/app/package.json b/app/package.json index 75c187dc..bbf76812 100644 --- a/app/package.json +++ b/app/package.json @@ -4,5 +4,8 @@ "version": "0.10.0", "license": "GPL-3.0", "description": "Designer for Thinreports", - "main": "main.js" + "main": "main.js", + "dependencies": { + "fontmetrics": "^1.0.0" + } } diff --git a/app/yarn.lock b/app/yarn.lock new file mode 100644 index 00000000..aba14a32 --- /dev/null +++ b/app/yarn.lock @@ -0,0 +1,7 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +fontmetrics@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fontmetrics/-/fontmetrics-1.0.0.tgz#38b205a1eb2e331a77f93fda4028c7037a2869a7" diff --git a/package.json b/package.json index f6969b2a..be9fe535 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "build": "node tasks/build.js", "release": "cross-env NODE_ENV=production npm run compile && npm run build", "watch": "node tasks/watch.js", - "postinstall": "cd app && npm install" + "postinstall": "cd app && yarn install" }, "devDependencies": { "archiver": "^2.0.3",