hob (empty) → 0.0.1.0
raw patch · 149 files changed
+14525/−0 lines, 149 filesdep +basedep +bytestringdep +containerssetup-changedbinary-added
Dependencies added: base, bytestring, containers, directory, filepath, glib, gtk-largeTreeStore, gtk3, gtksourceview3, hob, hspec, mtl, pango, system-filepath, text, transformers, vector
Files
- LICENSE +674/−0
- Setup.hs +6/−0
- app-data/themes/gtk/default/app-specific.css +10/−0
- app-data/themes/gtk/default/assets/check-dark.svg +17/−0
- app-data/themes/gtk/default/assets/check-insensitive-dark.svg +17/−0
- app-data/themes/gtk/default/assets/check-insensitive.svg +17/−0
- app-data/themes/gtk/default/assets/check-selected.svg +17/−0
- app-data/themes/gtk/default/assets/check.svg +17/−0
- app-data/themes/gtk/default/assets/mix-dark.svg +17/−0
- app-data/themes/gtk/default/assets/mix-insensitive-dark.svg +17/−0
- app-data/themes/gtk/default/assets/mix-insensitive.svg +17/−0
- app-data/themes/gtk/default/assets/mix-selected.svg +17/−0
- app-data/themes/gtk/default/assets/mix.svg +17/−0
- app-data/themes/gtk/default/assets/noise-texture-dark.png binary
- app-data/themes/gtk/default/assets/noise-texture.png binary
- app-data/themes/gtk/default/assets/pane-separator-grip-active.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-dark.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-hover-dark.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-hover.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-vertical-active.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-vertical-dark.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-vertical-hover-dark.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-vertical-hover.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip-vertical.svg +115/−0
- app-data/themes/gtk/default/assets/pane-separator-grip.svg +115/−0
- app-data/themes/gtk/default/assets/radio-dark.svg +17/−0
- app-data/themes/gtk/default/assets/radio-hover-dark.svg +17/−0
- app-data/themes/gtk/default/assets/radio-hover.svg +17/−0
- app-data/themes/gtk/default/assets/radio-insensitive-dark.svg +17/−0
- app-data/themes/gtk/default/assets/radio-insensitive.svg +17/−0
- app-data/themes/gtk/default/assets/radio-selected-hover.svg +17/−0
- app-data/themes/gtk/default/assets/radio-selected.svg +17/−0
- app-data/themes/gtk/default/assets/radio.svg +17/−0
- app-data/themes/gtk/default/assets/resize-grip-active.svg +125/−0
- app-data/themes/gtk/default/assets/resize-grip-dark.svg +125/−0
- app-data/themes/gtk/default/assets/resize-grip-hover-dark.svg +125/−0
- app-data/themes/gtk/default/assets/resize-grip-hover.svg +125/−0
- app-data/themes/gtk/default/assets/resize-grip.svg +125/−0
- app-data/themes/gtk/default/assets/scale-slider-down-active-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-active.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-fine-tune-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-fine-tune.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-hover-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-hover.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-down-insensitive-dark.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-down-insensitive.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-down.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-active-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-active.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-fine-tune-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-fine-tune.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-hover-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-hover.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-left-insensitive-dark.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-left-insensitive.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-left.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-active-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-active.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-fine-tune-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-fine-tune.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-hover-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-hover.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-right-insensitive-dark.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-right-insensitive.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-right.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-active-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-active.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-fine-tune-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-fine-tune.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-hover-dark.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-hover.svg +97/−0
- app-data/themes/gtk/default/assets/scale-slider-up-insensitive-dark.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-up-insensitive.svg +73/−0
- app-data/themes/gtk/default/assets/scale-slider-up.svg +97/−0
- app-data/themes/gtk/default/assets/thumbnail-frame.png binary
- app-data/themes/gtk/default/gtk-common.css +59/−0
- app-data/themes/gtk/default/gtk-dark.css +36/−0
- app-data/themes/gtk/default/gtk-fallback.css +15/−0
- app-data/themes/gtk/default/gtk-widgets-assets-dark.css +339/−0
- app-data/themes/gtk/default/gtk-widgets-assets.css +339/−0
- app-data/themes/gtk/default/gtk-widgets-backgrounds-and-texts.css +486/−0
- app-data/themes/gtk/default/gtk-widgets-borders.css +215/−0
- app-data/themes/gtk/default/gtk-widgets.css +2178/−0
- app-data/themes/gtk/default/gtk.css +31/−0
- app-data/themes/gtk/default/keybindings.css +10/−0
- app-data/themes/gtk/default/reset.css +63/−0
- app-data/themes/gtksourceview/molokai.xml +33/−0
- app-data/ui.glade +122/−0
- hob.cabal +71/−0
- src/hob.hs +55/−0
- src/lib/Hob/Command/CloseCurrentTab.hs +24/−0
- src/lib/Hob/Command/FindText.hs +54/−0
- src/lib/Hob/Command/FocusCommandEntry.hs +47/−0
- src/lib/Hob/Command/FocusNextTab.hs +22/−0
- src/lib/Hob/Command/FocusNumberedTab.hs +18/−0
- src/lib/Hob/Command/FocusPreviousTab.hs +22/−0
- src/lib/Hob/Command/FocusSidebar.hs +37/−0
- src/lib/Hob/Command/NewTab.hs +51/−0
- src/lib/Hob/Command/ReloadSidebarTree.hs +11/−0
- src/lib/Hob/Command/ReplaceText.hs +67/−0
- src/lib/Hob/Command/SaveCurrentTab.hs +59/−0
- src/lib/Hob/Context.hs +85/−0
- src/lib/Hob/Context/CommandMatcher.hs +33/−0
- src/lib/Hob/Context/Editor.hs +90/−0
- src/lib/Hob/Context/Events.hs +45/−0
- src/lib/Hob/Context/FileContext.hs +35/−0
- src/lib/Hob/Context/StyleContext.hs +43/−0
- src/lib/Hob/Context/Types.hs +110/−0
- src/lib/Hob/Context/UiContext.hs +14/−0
- src/lib/Hob/Control.hs +15/−0
- src/lib/Hob/DirectoryTree.hs +54/−0
- src/lib/Hob/Ui.hs +150/−0
- src/lib/Hob/Ui/CommandEntry.hs +86/−0
- src/lib/Hob/Ui/Editor.hs +217/−0
- src/lib/Hob/Ui/Editor/Search.hs +153/−0
- src/lib/Hob/Ui/Sidebar.hs +108/−0
- src/lib/Hob/Ui/SidebarSearch.hs +349/−0
- test/Hob/Command/CloseCurrentTabSpec.hs +35/−0
- test/Hob/Command/FindTextSpec.hs +70/−0
- test/Hob/Command/FocusCommandEntrySpec.hs +51/−0
- test/Hob/Command/FocusNextTabSpec.hs +54/−0
- test/Hob/Command/FocusNumberedTabSpec.hs +43/−0
- test/Hob/Command/FocusPreviousTabSpec.hs +54/−0
- test/Hob/Command/FocusSidebarSpec.hs +55/−0
- test/Hob/Command/NewTabSpec.hs +35/−0
- test/Hob/Command/ReloadSidebarTreeSpec.hs +69/−0
- test/Hob/Command/ReplaceTextSpec.hs +102/−0
- test/Hob/Command/SaveCurrentTabSpec.hs +108/−0
- test/Hob/Context/FileContextSpec.hs +23/−0
- test/Hob/Context/StyleContextSpec.hs +30/−0
- test/Hob/ContextSpec.hs +276/−0
- test/Hob/ControlSpec.hs +30/−0
- test/Hob/DirectoryTreeSpec.hs +72/−0
- test/Hob/Ui/CommandEntrySpec.hs +145/−0
- test/Hob/Ui/Editor/SearchSpec.hs +237/−0
- test/Hob/Ui/EditorSpec.hs +123/−0
- test/Hob/Ui/SidebarSearchSpec.hs +150/−0
- test/Hob/Ui/SidebarSpec.hs +61/−0
- test/Hob/UiSpec.hs +21/−0
- test/HobTest/Context/Default.hs +32/−0
- test/HobTest/Context/Stubbed.hs +41/−0
- test/HobTest/Control.hs +11/−0
- test/HobTest/Editor.hs +29/−0
- test/HobTest/Sidebar.hs +56/−0
- test/Spec.hs +2/−0
+ LICENSE view
@@ -0,0 +1,674 @@+ GNU GENERAL PUBLIC LICENSE+ Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++ Preamble++ The GNU General Public License is a free, copyleft license for+software and other kinds of works.++ The licenses for most software and other practical works are designed+to take away your freedom to share and change the works. By contrast,+the GNU General Public License is intended to guarantee your freedom to+share and change all versions of a program--to make sure it remains free+software for all its users. We, the Free Software Foundation, use the+GNU General Public License for most of our software; it applies also to+any other work released this way by its authors. You can apply it to+your programs, too.++ When we speak of free software, we are referring to freedom, not+price. Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+them if you wish), that you receive source code or can get it if you+want it, that you can change the software or use pieces of it in new+free programs, and that you know you can do these things.++ To protect your rights, we need to prevent others from denying you+these rights or asking you to surrender the rights. Therefore, you have+certain responsibilities if you distribute copies of the software, or if+you modify it: responsibilities to respect the freedom of others.++ For example, if you distribute copies of such a program, whether+gratis or for a fee, you must pass on to the recipients the same+freedoms that you received. You must make sure that they, too, receive+or can get the source code. And you must show them these terms so they+know their rights.++ Developers that use the GNU GPL protect your rights with two steps:+(1) assert copyright on the software, and (2) offer you this License+giving you legal permission to copy, distribute and/or modify it.++ For the developers' and authors' protection, the GPL clearly explains+that there is no warranty for this free software. For both users' and+authors' sake, the GPL requires that modified versions be marked as+changed, so that their problems will not be attributed erroneously to+authors of previous versions.++ Some devices are designed to deny users access to install or run+modified versions of the software inside them, although the manufacturer+can do so. This is fundamentally incompatible with the aim of+protecting users' freedom to change the software. The systematic+pattern of such abuse occurs in the area of products for individuals to+use, which is precisely where it is most unacceptable. Therefore, we+have designed this version of the GPL to prohibit the practice for those+products. If such problems arise substantially in other domains, we+stand ready to extend this provision to those domains in future versions+of the GPL, as needed to protect the freedom of users.++ Finally, every program is threatened constantly by software patents.+States should not allow patents to restrict development and use of+software on general-purpose computers, but in those that do, we wish to+avoid the special danger that patents applied to a free program could+make it effectively proprietary. To prevent this, the GPL assures that+patents cannot be used to render the program non-free.++ The precise terms and conditions for copying, distribution and+modification follow.++ TERMS AND CONDITIONS++ 0. Definitions.++ "This License" refers to version 3 of the GNU General Public License.++ "Copyright" also means copyright-like laws that apply to other kinds of+works, such as semiconductor masks.++ "The Program" refers to any copyrightable work licensed under this+License. Each licensee is addressed as "you". "Licensees" and+"recipients" may be individuals or organizations.++ To "modify" a work means to copy from or adapt all or part of the work+in a fashion requiring copyright permission, other than the making of an+exact copy. The resulting work is called a "modified version" of the+earlier work or a work "based on" the earlier work.++ A "covered work" means either the unmodified Program or a work based+on the Program.++ To "propagate" a work means to do anything with it that, without+permission, would make you directly or secondarily liable for+infringement under applicable copyright law, except executing it on a+computer or modifying a private copy. Propagation includes copying,+distribution (with or without modification), making available to the+public, and in some countries other activities as well.++ To "convey" a work means any kind of propagation that enables other+parties to make or receive copies. Mere interaction with a user through+a computer network, with no transfer of a copy, is not conveying.++ An interactive user interface displays "Appropriate Legal Notices"+to the extent that it includes a convenient and prominently visible+feature that (1) displays an appropriate copyright notice, and (2)+tells the user that there is no warranty for the work (except to the+extent that warranties are provided), that licensees may convey the+work under this License, and how to view a copy of this License. If+the interface presents a list of user commands or options, such as a+menu, a prominent item in the list meets this criterion.++ 1. Source Code.++ The "source code" for a work means the preferred form of the work+for making modifications to it. "Object code" means any non-source+form of a work.++ A "Standard Interface" means an interface that either is an official+standard defined by a recognized standards body, or, in the case of+interfaces specified for a particular programming language, one that+is widely used among developers working in that language.++ The "System Libraries" of an executable work include anything, other+than the work as a whole, that (a) is included in the normal form of+packaging a Major Component, but which is not part of that Major+Component, and (b) serves only to enable use of the work with that+Major Component, or to implement a Standard Interface for which an+implementation is available to the public in source code form. A+"Major Component", in this context, means a major essential component+(kernel, window system, and so on) of the specific operating system+(if any) on which the executable work runs, or a compiler used to+produce the work, or an object code interpreter used to run it.++ The "Corresponding Source" for a work in object code form means all+the source code needed to generate, install, and (for an executable+work) run the object code and to modify the work, including scripts to+control those activities. However, it does not include the work's+System Libraries, or general-purpose tools or generally available free+programs which are used unmodified in performing those activities but+which are not part of the work. For example, Corresponding Source+includes interface definition files associated with source files for+the work, and the source code for shared libraries and dynamically+linked subprograms that the work is specifically designed to require,+such as by intimate data communication or control flow between those+subprograms and other parts of the work.++ The Corresponding Source need not include anything that users+can regenerate automatically from other parts of the Corresponding+Source.++ The Corresponding Source for a work in source code form is that+same work.++ 2. Basic Permissions.++ All rights granted under this License are granted for the term of+copyright on the Program, and are irrevocable provided the stated+conditions are met. This License explicitly affirms your unlimited+permission to run the unmodified Program. The output from running a+covered work is covered by this License only if the output, given its+content, constitutes a covered work. This License acknowledges your+rights of fair use or other equivalent, as provided by copyright law.++ You may make, run and propagate covered works that you do not+convey, without conditions so long as your license otherwise remains+in force. You may convey covered works to others for the sole purpose+of having them make modifications exclusively for you, or provide you+with facilities for running those works, provided that you comply with+the terms of this License in conveying all material for which you do+not control copyright. Those thus making or running the covered works+for you must do so exclusively on your behalf, under your direction+and control, on terms that prohibit them from making any copies of+your copyrighted material outside their relationship with you.++ Conveying under any other circumstances is permitted solely under+the conditions stated below. Sublicensing is not allowed; section 10+makes it unnecessary.++ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.++ No covered work shall be deemed part of an effective technological+measure under any applicable law fulfilling obligations under article+11 of the WIPO copyright treaty adopted on 20 December 1996, or+similar laws prohibiting or restricting circumvention of such+measures.++ When you convey a covered work, you waive any legal power to forbid+circumvention of technological measures to the extent such circumvention+is effected by exercising rights under this License with respect to+the covered work, and you disclaim any intention to limit operation or+modification of the work as a means of enforcing, against the work's+users, your or third parties' legal rights to forbid circumvention of+technological measures.++ 4. Conveying Verbatim Copies.++ You may convey verbatim copies of the Program's source code as you+receive it, in any medium, provided that you conspicuously and+appropriately publish on each copy an appropriate copyright notice;+keep intact all notices stating that this License and any+non-permissive terms added in accord with section 7 apply to the code;+keep intact all notices of the absence of any warranty; and give all+recipients a copy of this License along with the Program.++ You may charge any price or no price for each copy that you convey,+and you may offer support or warranty protection for a fee.++ 5. Conveying Modified Source Versions.++ You may convey a work based on the Program, or the modifications to+produce it from the Program, in the form of source code under the+terms of section 4, provided that you also meet all of these conditions:++ a) The work must carry prominent notices stating that you modified+ it, and giving a relevant date.++ b) The work must carry prominent notices stating that it is+ released under this License and any conditions added under section+ 7. This requirement modifies the requirement in section 4 to+ "keep intact all notices".++ c) You must license the entire work, as a whole, under this+ License to anyone who comes into possession of a copy. This+ License will therefore apply, along with any applicable section 7+ additional terms, to the whole of the work, and all its parts,+ regardless of how they are packaged. This License gives no+ permission to license the work in any other way, but it does not+ invalidate such permission if you have separately received it.++ d) If the work has interactive user interfaces, each must display+ Appropriate Legal Notices; however, if the Program has interactive+ interfaces that do not display Appropriate Legal Notices, your+ work need not make them do so.++ A compilation of a covered work with other separate and independent+works, which are not by their nature extensions of the covered work,+and which are not combined with it such as to form a larger program,+in or on a volume of a storage or distribution medium, is called an+"aggregate" if the compilation and its resulting copyright are not+used to limit the access or legal rights of the compilation's users+beyond what the individual works permit. Inclusion of a covered work+in an aggregate does not cause this License to apply to the other+parts of the aggregate.++ 6. Conveying Non-Source Forms.++ You may convey a covered work in object code form under the terms+of sections 4 and 5, provided that you also convey the+machine-readable Corresponding Source under the terms of this License,+in one of these ways:++ a) Convey the object code in, or embodied in, a physical product+ (including a physical distribution medium), accompanied by the+ Corresponding Source fixed on a durable physical medium+ customarily used for software interchange.++ b) Convey the object code in, or embodied in, a physical product+ (including a physical distribution medium), accompanied by a+ written offer, valid for at least three years and valid for as+ long as you offer spare parts or customer support for that product+ model, to give anyone who possesses the object code either (1) a+ copy of the Corresponding Source for all the software in the+ product that is covered by this License, on a durable physical+ medium customarily used for software interchange, for a price no+ more than your reasonable cost of physically performing this+ conveying of source, or (2) access to copy the+ Corresponding Source from a network server at no charge.++ c) Convey individual copies of the object code with a copy of the+ written offer to provide the Corresponding Source. This+ alternative is allowed only occasionally and noncommercially, and+ only if you received the object code with such an offer, in accord+ with subsection 6b.++ d) Convey the object code by offering access from a designated+ place (gratis or for a charge), and offer equivalent access to the+ Corresponding Source in the same way through the same place at no+ further charge. You need not require recipients to copy the+ Corresponding Source along with the object code. If the place to+ copy the object code is a network server, the Corresponding Source+ may be on a different server (operated by you or a third party)+ that supports equivalent copying facilities, provided you maintain+ clear directions next to the object code saying where to find the+ Corresponding Source. Regardless of what server hosts the+ Corresponding Source, you remain obligated to ensure that it is+ available for as long as needed to satisfy these requirements.++ e) Convey the object code using peer-to-peer transmission, provided+ you inform other peers where the object code and Corresponding+ Source of the work are being offered to the general public at no+ charge under subsection 6d.++ A separable portion of the object code, whose source code is excluded+from the Corresponding Source as a System Library, need not be+included in conveying the object code work.++ A "User Product" is either (1) a "consumer product", which means any+tangible personal property which is normally used for personal, family,+or household purposes, or (2) anything designed or sold for incorporation+into a dwelling. In determining whether a product is a consumer product,+doubtful cases shall be resolved in favor of coverage. For a particular+product received by a particular user, "normally used" refers to a+typical or common use of that class of product, regardless of the status+of the particular user or of the way in which the particular user+actually uses, or expects or is expected to use, the product. A product+is a consumer product regardless of whether the product has substantial+commercial, industrial or non-consumer uses, unless such uses represent+the only significant mode of use of the product.++ "Installation Information" for a User Product means any methods,+procedures, authorization keys, or other information required to install+and execute modified versions of a covered work in that User Product from+a modified version of its Corresponding Source. The information must+suffice to ensure that the continued functioning of the modified object+code is in no case prevented or interfered with solely because+modification has been made.++ If you convey an object code work under this section in, or with, or+specifically for use in, a User Product, and the conveying occurs as+part of a transaction in which the right of possession and use of the+User Product is transferred to the recipient in perpetuity or for a+fixed term (regardless of how the transaction is characterized), the+Corresponding Source conveyed under this section must be accompanied+by the Installation Information. But this requirement does not apply+if neither you nor any third party retains the ability to install+modified object code on the User Product (for example, the work has+been installed in ROM).++ The requirement to provide Installation Information does not include a+requirement to continue to provide support service, warranty, or updates+for a work that has been modified or installed by the recipient, or for+the User Product in which it has been modified or installed. Access to a+network may be denied when the modification itself materially and+adversely affects the operation of the network or violates the rules and+protocols for communication across the network.++ Corresponding Source conveyed, and Installation Information provided,+in accord with this section must be in a format that is publicly+documented (and with an implementation available to the public in+source code form), and must require no special password or key for+unpacking, reading or copying.++ 7. Additional Terms.++ "Additional permissions" are terms that supplement the terms of this+License by making exceptions from one or more of its conditions.+Additional permissions that are applicable to the entire Program shall+be treated as though they were included in this License, to the extent+that they are valid under applicable law. If additional permissions+apply only to part of the Program, that part may be used separately+under those permissions, but the entire Program remains governed by+this License without regard to the additional permissions.++ When you convey a copy of a covered work, you may at your option+remove any additional permissions from that copy, or from any part of+it. (Additional permissions may be written to require their own+removal in certain cases when you modify the work.) You may place+additional permissions on material, added by you to a covered work,+for which you have or can give appropriate copyright permission.++ Notwithstanding any other provision of this License, for material you+add to a covered work, you may (if authorized by the copyright holders of+that material) supplement the terms of this License with terms:++ a) Disclaiming warranty or limiting liability differently from the+ terms of sections 15 and 16 of this License; or++ b) Requiring preservation of specified reasonable legal notices or+ author attributions in that material or in the Appropriate Legal+ Notices displayed by works containing it; or++ c) Prohibiting misrepresentation of the origin of that material, or+ requiring that modified versions of such material be marked in+ reasonable ways as different from the original version; or++ d) Limiting the use for publicity purposes of names of licensors or+ authors of the material; or++ e) Declining to grant rights under trademark law for use of some+ trade names, trademarks, or service marks; or++ f) Requiring indemnification of licensors and authors of that+ material by anyone who conveys the material (or modified versions of+ it) with contractual assumptions of liability to the recipient, for+ any liability that these contractual assumptions directly impose on+ those licensors and authors.++ All other non-permissive additional terms are considered "further+restrictions" within the meaning of section 10. If the Program as you+received it, or any part of it, contains a notice stating that it is+governed by this License along with a term that is a further+restriction, you may remove that term. If a license document contains+a further restriction but permits relicensing or conveying under this+License, you may add to a covered work material governed by the terms+of that license document, provided that the further restriction does+not survive such relicensing or conveying.++ If you add terms to a covered work in accord with this section, you+must place, in the relevant source files, a statement of the+additional terms that apply to those files, or a notice indicating+where to find the applicable terms.++ Additional terms, permissive or non-permissive, may be stated in the+form of a separately written license, or stated as exceptions;+the above requirements apply either way.++ 8. Termination.++ You may not propagate or modify a covered work except as expressly+provided under this License. Any attempt otherwise to propagate or+modify it is void, and will automatically terminate your rights under+this License (including any patent licenses granted under the third+paragraph of section 11).++ However, if you cease all violation of this License, then your+license from a particular copyright holder is reinstated (a)+provisionally, unless and until the copyright holder explicitly and+finally terminates your license, and (b) permanently, if the copyright+holder fails to notify you of the violation by some reasonable means+prior to 60 days after the cessation.++ Moreover, your license from a particular copyright holder is+reinstated permanently if the copyright holder notifies you of the+violation by some reasonable means, this is the first time you have+received notice of violation of this License (for any work) from that+copyright holder, and you cure the violation prior to 30 days after+your receipt of the notice.++ Termination of your rights under this section does not terminate the+licenses of parties who have received copies or rights from you under+this License. If your rights have been terminated and not permanently+reinstated, you do not qualify to receive new licenses for the same+material under section 10.++ 9. Acceptance Not Required for Having Copies.++ You are not required to accept this License in order to receive or+run a copy of the Program. Ancillary propagation of a covered work+occurring solely as a consequence of using peer-to-peer transmission+to receive a copy likewise does not require acceptance. However,+nothing other than this License grants you permission to propagate or+modify any covered work. These actions infringe copyright if you do+not accept this License. Therefore, by modifying or propagating a+covered work, you indicate your acceptance of this License to do so.++ 10. Automatic Licensing of Downstream Recipients.++ Each time you convey a covered work, the recipient automatically+receives a license from the original licensors, to run, modify and+propagate that work, subject to this License. You are not responsible+for enforcing compliance by third parties with this License.++ An "entity transaction" is a transaction transferring control of an+organization, or substantially all assets of one, or subdividing an+organization, or merging organizations. If propagation of a covered+work results from an entity transaction, each party to that+transaction who receives a copy of the work also receives whatever+licenses to the work the party's predecessor in interest had or could+give under the previous paragraph, plus a right to possession of the+Corresponding Source of the work from the predecessor in interest, if+the predecessor has it or can get it with reasonable efforts.++ You may not impose any further restrictions on the exercise of the+rights granted or affirmed under this License. For example, you may+not impose a license fee, royalty, or other charge for exercise of+rights granted under this License, and you may not initiate litigation+(including a cross-claim or counterclaim in a lawsuit) alleging that+any patent claim is infringed by making, using, selling, offering for+sale, or importing the Program or any portion of it.++ 11. Patents.++ A "contributor" is a copyright holder who authorizes use under this+License of the Program or a work on which the Program is based. The+work thus licensed is called the contributor's "contributor version".++ A contributor's "essential patent claims" are all patent claims+owned or controlled by the contributor, whether already acquired or+hereafter acquired, that would be infringed by some manner, permitted+by this License, of making, using, or selling its contributor version,+but do not include claims that would be infringed only as a+consequence of further modification of the contributor version. For+purposes of this definition, "control" includes the right to grant+patent sublicenses in a manner consistent with the requirements of+this License.++ Each contributor grants you a non-exclusive, worldwide, royalty-free+patent license under the contributor's essential patent claims, to+make, use, sell, offer for sale, import and otherwise run, modify and+propagate the contents of its contributor version.++ In the following three paragraphs, a "patent license" is any express+agreement or commitment, however denominated, not to enforce a patent+(such as an express permission to practice a patent or covenant not to+sue for patent infringement). To "grant" such a patent license to a+party means to make such an agreement or commitment not to enforce a+patent against the party.++ If you convey a covered work, knowingly relying on a patent license,+and the Corresponding Source of the work is not available for anyone+to copy, free of charge and under the terms of this License, through a+publicly available network server or other readily accessible means,+then you must either (1) cause the Corresponding Source to be so+available, or (2) arrange to deprive yourself of the benefit of the+patent license for this particular work, or (3) arrange, in a manner+consistent with the requirements of this License, to extend the patent+license to downstream recipients. "Knowingly relying" means you have+actual knowledge that, but for the patent license, your conveying the+covered work in a country, or your recipient's use of the covered work+in a country, would infringe one or more identifiable patents in that+country that you have reason to believe are valid.++ If, pursuant to or in connection with a single transaction or+arrangement, you convey, or propagate by procuring conveyance of, a+covered work, and grant a patent license to some of the parties+receiving the covered work authorizing them to use, propagate, modify+or convey a specific copy of the covered work, then the patent license+you grant is automatically extended to all recipients of the covered+work and works based on it.++ A patent license is "discriminatory" if it does not include within+the scope of its coverage, prohibits the exercise of, or is+conditioned on the non-exercise of one or more of the rights that are+specifically granted under this License. You may not convey a covered+work if you are a party to an arrangement with a third party that is+in the business of distributing software, under which you make payment+to the third party based on the extent of your activity of conveying+the work, and under which the third party grants, to any of the+parties who would receive the covered work from you, a discriminatory+patent license (a) in connection with copies of the covered work+conveyed by you (or copies made from those copies), or (b) primarily+for and in connection with specific products or compilations that+contain the covered work, unless you entered into that arrangement,+or that patent license was granted, prior to 28 March 2007.++ Nothing in this License shall be construed as excluding or limiting+any implied license or other defenses to infringement that may+otherwise be available to you under applicable patent law.++ 12. No Surrender of Others' Freedom.++ If conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License. If you cannot convey a+covered work so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you may+not convey it at all. For example, if you agree to terms that obligate you+to collect a royalty for further conveying from those to whom you convey+the Program, the only way you could satisfy both those terms and this+License would be to refrain entirely from conveying the Program.++ 13. Use with the GNU Affero General Public License.++ Notwithstanding any other provision of this License, you have+permission to link or combine any covered work with a work licensed+under version 3 of the GNU Affero General Public License into a single+combined work, and to convey the resulting work. The terms of this+License will continue to apply to the part which is the covered work,+but the special requirements of the GNU Affero General Public License,+section 13, concerning interaction through a network will apply to the+combination as such.++ 14. Revised Versions of this License.++ The Free Software Foundation may publish revised and/or new versions of+the GNU General Public License from time to time. Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++ Each version is given a distinguishing version number. If the+Program specifies that a certain numbered version of the GNU General+Public License "or any later version" applies to it, you have the+option of following the terms and conditions either of that numbered+version or of any later version published by the Free Software+Foundation. If the Program does not specify a version number of the+GNU General Public License, you may choose any version ever published+by the Free Software Foundation.++ If the Program specifies that a proxy can decide which future+versions of the GNU General Public License can be used, that proxy's+public statement of acceptance of a version permanently authorizes you+to choose that version for the Program.++ Later license versions may give you additional or different+permissions. However, no additional obligations are imposed on any+author or copyright holder as a result of your choosing to follow a+later version.++ 15. Disclaimer of Warranty.++ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++ 16. Limitation of Liability.++ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF+SUCH DAMAGES.++ 17. Interpretation of Sections 15 and 16.++ If the disclaimer of warranty and limitation of liability provided+above cannot be given local legal effect according to their terms,+reviewing courts shall apply local law that most closely approximates+an absolute waiver of all civil liability in connection with the+Program, unless a warranty or assumption of liability accompanies a+copy of the Program in return for a fee.++ END OF TERMS AND CONDITIONS++ How to Apply These Terms to Your New Programs++ If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++ To do so, attach the following notices to the program. It is safest+to attach them to the start of each source file to most effectively+state the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++ <one line to give the program's name and a brief idea of what it does.>+ Copyright (C) <year> <name of author>++ 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 <http://www.gnu.org/licenses/>.++Also add information on how to contact you by electronic and paper mail.++ If the program does terminal interaction, make it output a short+notice like this when it starts in an interactive mode:++ <program> Copyright (C) <year> <name of author>+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+ This is free software, and you are welcome to redistribute it+ under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License. Of course, your program's commands+might be different; for a GUI interface, you would use an "about box".++ You should also get your employer (if you work as a programmer) or school,+if any, to sign a "copyright disclaimer" for the program, if necessary.+For more information on this, and how to apply and follow the GNU GPL, see+<http://www.gnu.org/licenses/>.++ The GNU General Public License does not permit incorporating your program+into proprietary programs. If your program is a subroutine library, you+may consider it more useful to permit linking proprietary applications with+the library. If this is what you want to do, use the GNU Lesser General+Public License instead of this License. But first, please read+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
+ app-data/themes/gtk/default/app-specific.css view
@@ -0,0 +1,10 @@+.entry.error, .entry.error:focus {+ color: #FF7777;+ background-color: mix(@theme_bg_color, red, 0.1);+ border-color: red;+}++.entry.error:selected {+ color: #FFEE99;+ background-color: mix(@theme_bg_color, yellow, 0.2);+}
+ app-data/themes/gtk/default/assets/check-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-61.001 -787)">+ <path id="path8913-6-7-1-5" style="block-progression:tb;text-indent:0;color:#eeeeec;text-transform:none;fill:#eeeeec" d="m72.938 790.94-4.938 4.94l-1.9375-1.9375-2.125 2.125 3 3 1.0625 1.0625 1.0625-1.0625 6-6-2.125-2.125z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/check-insensitive-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-61.001 -787)">+ <path id="path8913-6-7-1-5" style="opacity:0.5;block-progression:tb;text-indent:0;color:#eeeeec;text-transform:none;fill:#eeeeec" d="m72.938 790.94-4.938 4.94l-1.9375-1.9375-2.125 2.125 3 3 1.0625 1.0625 1.0625-1.0625 6-6-2.125-2.125z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/check-insensitive.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-61.001 -787)">+ <path id="path8913-6-7-1-5" style="opacity:0.5;block-progression:tb;text-indent:0;color:#2e3436;text-transform:none;fill:#2e3436" d="m72.938 790.94-4.938 4.94l-1.9375-1.9375-2.125 2.125 3 3 1.0625 1.0625 1.0625-1.0625 6-6-2.125-2.125z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/check-selected.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-61.001 -787)">+ <path id="path8913-6-7-1-5" style="block-progression:tb;text-indent:0;color:#ffffff;text-transform:none;fill:#ffffff" d="m72.938 790.94-4.938 4.94l-1.9375-1.9375-2.125 2.125 3 3 1.0625 1.0625 1.0625-1.0625 6-6-2.125-2.125z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/check.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-61.001 -787)">+ <path id="path8913-6-7-1-5" style="block-progression:tb;text-indent:0;color:#2e3436;text-transform:none;fill:#2e3436" d="m72.938 790.94-4.938 4.94l-1.9375-1.9375-2.125 2.125 3 3 1.0625 1.0625 1.0625-1.0625 6-6-2.125-2.125z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/mix-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-40 -726)">+ <rect id="rect31984" style="color:#eeeeec;fill:#eeeeec" height="2.0002" width="9.9996" y="733" x="43"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/mix-insensitive-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-40 -726)">+ <rect id="rect31984" style="opacity:0.5;color:#eeeeec;fill:#eeeeec" height="2.0002" width="9.9996" y="733" x="43"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/mix-insensitive.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-40 -726)">+ <rect id="rect31984" style="opacity:0.5;color:#2e3436;fill:#2e3436" height="2.0002" width="9.9996" y="733" x="43"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/mix-selected.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-40 -726)">+ <rect id="rect31984" style="color:#ffffff;fill:#ffffff" height="2.0002" width="9.9996" y="733" x="43"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/mix.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="translate(-40 -726)">+ <rect id="rect31984" style="color:#2e3436;fill:#2e3436" height="2.0002" width="9.9996" y="733" x="43"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/noise-texture-dark.png view
binary file changed (absent → 69136 bytes)
+ app-data/themes/gtk/default/assets/noise-texture.png view
binary file changed (absent → 69136 bytes)
+ app-data/themes/gtk/default/assets/pane-separator-grip-active.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="2"+ height="22"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="32.454545"+ inkscape:cx="1"+ inkscape:cy="11"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3836"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,6)">+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3838"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3840"+ sodipodi:cx="1"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,6 A 1,1 0 1 1 0,6 1,1 0 1 1 2,6 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3842"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3844"+ sodipodi:cx="1"+ sodipodi:cy="16"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,16 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3846"+ sodipodi:cx="1"+ sodipodi:cy="21"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,21 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-dark.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="2"+ height="22"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="32.454545"+ inkscape:cx="1"+ inkscape:cy="11"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3836"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,6)">+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3838"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3840"+ sodipodi:cx="1"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,6 A 1,1 0 1 1 0,6 1,1 0 1 1 2,6 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3842"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3844"+ sodipodi:cx="1"+ sodipodi:cy="16"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,16 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3846"+ sodipodi:cx="1"+ sodipodi:cy="21"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,21 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-hover-dark.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="2"+ height="22"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="32.454545"+ inkscape:cx="1"+ inkscape:cy="11"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3836"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,6)">+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3838"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3840"+ sodipodi:cx="1"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,6 A 1,1 0 1 1 0,6 1,1 0 1 1 2,6 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3842"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3844"+ sodipodi:cx="1"+ sodipodi:cy="16"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,16 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3846"+ sodipodi:cx="1"+ sodipodi:cy="21"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,21 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-hover.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="2"+ height="22"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="32.454545"+ inkscape:cx="1"+ inkscape:cy="11"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3836"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,6)">+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3838"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3840"+ sodipodi:cx="1"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,6 A 1,1 0 1 1 0,6 1,1 0 1 1 2,6 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3842"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3844"+ sodipodi:cx="1"+ sodipodi:cy="16"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,16 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3846"+ sodipodi:cx="1"+ sodipodi:cy="21"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,21 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-vertical-active.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="22"+ height="2"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip-vertical.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="60.954545"+ inkscape:cx="11"+ inkscape:cy="1"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3757"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-14)">+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3759"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3761"+ sodipodi:cx="6"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,1 A 1,1 0 1 1 5,1 1,1 0 1 1 7,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3763"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3765"+ sodipodi:cx="16"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 17,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3767"+ sodipodi:cx="21"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 22,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-vertical-dark.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="22"+ height="2"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip-vertical.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="60.954545"+ inkscape:cx="11"+ inkscape:cy="1"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3757"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-14)">+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3759"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3761"+ sodipodi:cx="6"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,1 A 1,1 0 1 1 5,1 1,1 0 1 1 7,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3763"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3765"+ sodipodi:cx="16"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 17,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3767"+ sodipodi:cx="21"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 22,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-vertical-hover-dark.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="22"+ height="2"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip-vertical.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="60.954545"+ inkscape:cx="11"+ inkscape:cy="1"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3757"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-14)">+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3759"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3761"+ sodipodi:cx="6"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,1 A 1,1 0 1 1 5,1 1,1 0 1 1 7,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3763"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3765"+ sodipodi:cx="16"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 17,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3767"+ sodipodi:cx="21"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 22,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-vertical-hover.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="22"+ height="2"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip-vertical.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="60.954545"+ inkscape:cx="11"+ inkscape:cy="1"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3757"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-14)">+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3759"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3761"+ sodipodi:cx="6"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,1 A 1,1 0 1 1 5,1 1,1 0 1 1 7,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3763"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3765"+ sodipodi:cx="16"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 17,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3767"+ sodipodi:cx="21"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 22,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip-vertical.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="22"+ height="2"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip-vertical.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="60.954545"+ inkscape:cx="11"+ inkscape:cy="1"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3757"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-14)">+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3759"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3761"+ sodipodi:cx="6"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,1 A 1,1 0 1 1 5,1 1,1 0 1 1 7,1 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3763"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3765"+ sodipodi:cx="16"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 17,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3767"+ sodipodi:cx="21"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 22,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,14)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/pane-separator-grip.svg view
@@ -0,0 +1,115 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="2"+ height="22"+ id="svg32934"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="pane-separator-grip.svg">+ <defs+ id="defs32936" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="32.454545"+ inkscape:cx="1"+ inkscape:cy="11"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3836"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata32939">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,6)">+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3838"+ sodipodi:cx="1"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,1 A 1,1 0 1 1 0,1 1,1 0 1 1 2,1 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3840"+ sodipodi:cx="1"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 2,6 A 1,1 0 1 1 0,6 1,1 0 1 1 2,6 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3842"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3844"+ sodipodi:cx="1"+ sodipodi:cy="16"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,16 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3846"+ sodipodi:cx="1"+ sodipodi:cy="21"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,21 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,-6)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="color:#eeeeec;text-indent:0pt;text-transform:none;fill:#eeeeec" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-hover-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="color:#babdb6;text-indent:0pt;text-transform:none;fill:#babdb6" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-hover.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="color:#888a85;text-indent:0pt;text-transform:none;fill:#888a85" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-insensitive-dark.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="opacity:0.5;color:#eeeeec;text-indent:0pt;text-transform:none;fill:#eeeeec" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-insensitive.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="opacity:0.5;color:#2e3436;text-indent:0pt;text-transform:none;fill:#2e3436" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-selected-hover.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="opacity:0.5;color:#ffffff;text-indent:0pt;text-transform:none;fill:#ffffff" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio-selected.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="color:#ffffff;text-indent:0pt;text-transform:none;fill:#ffffff" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/radio.svg view
@@ -0,0 +1,17 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->+<svg id="svg7384" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">+ <title id="title9167">Gnome Symbolic Icon Theme</title>+ <metadata id="metadata90">+ <rdf:RDF>+ <cc:Work rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>+ <dc:title>Gnome Symbolic Icon Theme</dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g id="layer12" transform="matrix(0.88734967,0,0,0.54841228,-578.5098,-131.88177)">+ <path id="path4646-0" style="color:#2e3436;text-indent:0pt;text-transform:none;fill:#2e3436" d="m 665.47588,255.0668 a 4.5078058,7.2937827 0 1 1 -9.01561,0 4.5078058,7.2937827 0 1 1 9.01561,0 z"/>+ </g>+</svg>
+ app-data/themes/gtk/default/assets/resize-grip-active.svg view
@@ -0,0 +1,125 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="12"+ height="12"+ id="svg17653"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="resize-grip.svg">+ <defs+ id="defs17655" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="59.5"+ inkscape:cx="6"+ inkscape:cy="6"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3758"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata17658">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-4)">+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3776"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3778"+ sodipodi:cx="11"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,6 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3780"+ sodipodi:cx="11"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3782"+ sodipodi:cx="6"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 7,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3784"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#4e9a06;fill-opacity:1;stroke:none"+ id="path3786"+ sodipodi:cx="6"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,6 A 1,1 0 1 1 5,6 1,1 0 1 1 7,6 z"+ transform="translate(0,4)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/resize-grip-dark.svg view
@@ -0,0 +1,125 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="12"+ height="12"+ id="svg17653"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="resize-grip.svg">+ <defs+ id="defs17655" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="59.5"+ inkscape:cx="6"+ inkscape:cy="6"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3758"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata17658">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-4)">+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3776"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3778"+ sodipodi:cx="11"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,6 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3780"+ sodipodi:cx="11"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3782"+ sodipodi:cx="6"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 7,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3784"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#babdb6;fill-opacity:1;stroke:none"+ id="path3786"+ sodipodi:cx="6"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,6 A 1,1 0 1 1 5,6 1,1 0 1 1 7,6 z"+ transform="translate(0,4)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/resize-grip-hover-dark.svg view
@@ -0,0 +1,125 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="12"+ height="12"+ id="svg17653"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="resize-grip.svg">+ <defs+ id="defs17655" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="59.5"+ inkscape:cx="6"+ inkscape:cy="6"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3758"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata17658">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-4)">+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3776"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3778"+ sodipodi:cx="11"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,6 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3780"+ sodipodi:cx="11"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3782"+ sodipodi:cx="6"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 7,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3784"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ id="path3786"+ sodipodi:cx="6"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,6 A 1,1 0 1 1 5,6 1,1 0 1 1 7,6 z"+ transform="translate(0,4)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/resize-grip-hover.svg view
@@ -0,0 +1,125 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="12"+ height="12"+ id="svg17653"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="resize-grip.svg">+ <defs+ id="defs17655" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="59.5"+ inkscape:cx="6"+ inkscape:cy="6"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3758"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata17658">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-4)">+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3776"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3778"+ sodipodi:cx="11"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,6 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3780"+ sodipodi:cx="11"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3782"+ sodipodi:cx="6"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 7,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3784"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#2e3436;fill-opacity:1;stroke:none"+ id="path3786"+ sodipodi:cx="6"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,6 A 1,1 0 1 1 5,6 1,1 0 1 1 7,6 z"+ transform="translate(0,4)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/resize-grip.svg view
@@ -0,0 +1,125 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="12"+ height="12"+ id="svg17653"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="resize-grip.svg">+ <defs+ id="defs17655" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="59.5"+ inkscape:cx="6"+ inkscape:cy="6"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:grid-bbox="true"+ inkscape:document-units="px"+ inkscape:window-width="1920"+ inkscape:window-height="917"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid3758"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata17658">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title />+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ id="layer1"+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ transform="translate(0,-4)">+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3776"+ sodipodi:cx="11"+ sodipodi:cy="1"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,1 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3778"+ sodipodi:cx="11"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,6 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3780"+ sodipodi:cx="11"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 12,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3782"+ sodipodi:cx="6"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 7,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3784"+ sodipodi:cx="1"+ sodipodi:cy="11"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="m 2,11 a 1,1 0 1 1 -2,0 1,1 0 1 1 2,0 z"+ transform="translate(0,4)" />+ <path+ sodipodi:type="arc"+ style="fill:#888a85;fill-opacity:1;stroke:none"+ id="path3786"+ sodipodi:cx="6"+ sodipodi:cy="6"+ sodipodi:rx="1"+ sodipodi:ry="1"+ d="M 7,6 A 1,1 0 1 1 5,6 1,1 0 1 1 7,6 z"+ transform="translate(0,4)" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-active-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-active.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#4b4e4c;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#2c2f2f;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-fine-tune-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#536443;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#3B4F32;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-fine-tune.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#DCEBCE;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#C4D5B3;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-hover-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-hover.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-insensitive-dark.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:0.5;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#414544;fill-opacity:1;stroke:none"+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down-insensitive.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:0.5;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-down.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-left.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#f7f7f6;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#d4d6d1;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="1"+ x2="12"+ y2="23"+ gradientUnits="userSpaceOnUse"+ gradientTransform="translate(0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,12 12,-12 z m 0,0 c 0,-6.6274 5.3726,-12 12,-12 6.6274,0 12,5.3726 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,11 11,-11 z m 0,0 c 0,-6.0751 4.9249,-11 11,-11 6.0751,0 11,4.9249 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-active-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-active.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#4b4e4c;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#2c2f2f;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-fine-tune-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#536443;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#3B4F32;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-fine-tune.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#DCEBCE;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#C4D5B3;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-hover-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-hover.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-insensitive-dark.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:0.5;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#414544;fill-opacity:1;stroke:none"+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left-insensitive.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:0.5;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-left.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-right.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#f7f7f6;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#d4d6d1;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,-1,0,24,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 -12,12 12,12 z m 0,0 c 6.6274,0 12,5.3726 12,12 0,6.6274 -5.3726,12 -12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 -11,11 11,11 z m 0,0 c 6.0751,0 11,4.9249 11,11 0,6.0751 -4.9249,11 -11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-active-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-active.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#4b4e4c;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#2c2f2f;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-fine-tune-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#536443;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#3B4F32;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-fine-tune.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#DCEBCE;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#C4D5B3;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-hover-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-hover.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-insensitive-dark.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:0.5;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#414544;fill-opacity:1;stroke:none"+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right-insensitive.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:0.5;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-right.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-up.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#f7f7f6;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#d4d6d1;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="1"+ y1="12"+ x2="23"+ y2="12"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(0,1,1,0,0,1028.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 12,1028.3622 12,12 -12,12 z m 0,0 c -6.6274,0 -12,5.3726 -12,12 0,6.6274 5.3726,12 12,12"+ inkscape:connector-curvature="0" />+ <path+ d="m 12,1029.3622 11,11 -11,11 z m 0,0 c -6.0751,0 -11,4.9249 -11,11 0,6.0751 4.9249,11 11,11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-active-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-active.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#4b4e4c;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#2c2f2f;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-fine-tune-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#536443;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#3B4F32;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#63A129;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-fine-tune.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#DCEBCE;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#C4D5B3;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#59971F;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-hover-dark.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#555753;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#373c3d;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-hover.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#ffffff;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#e1e3de;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-insensitive-dark.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#0B0D0D;fill-opacity:0.5;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#414544;fill-opacity:1;stroke:none"+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up-insensitive.svg view
@@ -0,0 +1,73 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:0.5;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ id="path3765"+ style="fill:#eeeeec;fill-opacity:1;stroke:none"+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/scale-slider-up.svg view
@@ -0,0 +1,97 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:xlink="http://www.w3.org/1999/xlink"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="24"+ height="24"+ id="svg2"+ version="1.1"+ inkscape:version="0.48.4 r9939"+ sodipodi:docname="scale-slider-down.svg">+ <defs+ id="defs4">+ <linearGradient+ id="linearGradient3771">+ <stop+ style="stop-color:#f7f7f6;stop-opacity:1;"+ offset="0"+ id="stop3773" />+ <stop+ style="stop-color:#d4d6d1;stop-opacity:1;"+ offset="1"+ id="stop3775" />+ </linearGradient>+ <linearGradient+ inkscape:collect="always"+ xlink:href="#linearGradient3771"+ id="linearGradient3777"+ x1="12"+ y1="23"+ x2="12"+ y2="1"+ gradientUnits="userSpaceOnUse"+ gradientTransform="matrix(1,0,0,-1,0,1052.3622)" />+ </defs>+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="29.541667"+ inkscape:cx="12"+ inkscape:cy="12"+ inkscape:document-units="px"+ inkscape:current-layer="layer1"+ showgrid="true"+ inkscape:window-width="1920"+ inkscape:window-height="912"+ inkscape:window-x="0"+ inkscape:window-y="32"+ inkscape:window-maximized="1">+ <inkscape:grid+ type="xygrid"+ id="grid2985"+ empspacing="5"+ visible="true"+ enabled="true"+ snapvisiblegridlinesonly="true" />+ </sodipodi:namedview>+ <metadata+ id="metadata7">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="レイヤー 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(0,-1028.3622)">+ <path+ id="path2989"+ style="fill:#A1A49E;fill-opacity:1;stroke:none"+ d="m 0,1040.3622 12,-12 12,12 z m 0,0 c 3.0757981e-7,6.6274 5.3725836,12 12.000001,12 6.627416,0 11.999999,-5.3726 11.999999,-12"+ inkscape:connector-curvature="0" />+ <path+ d="m 1,1040.3622 11,-11 11,11 z m 0,0 c 3e-7,6.0751 4.9248683,11 11.000001,11 6.075132,0 10.999999,-4.9249 10.999999,-11"+ style="fill:url(#linearGradient3777);fill-opacity:1;stroke:none"+ id="path3769"+ inkscape:connector-curvature="0" />+ </g>+</svg>
+ app-data/themes/gtk/default/assets/thumbnail-frame.png view
binary file changed (absent → 832 bytes)
+ app-data/themes/gtk/default/gtk-common.css view
@@ -0,0 +1,59 @@+/* common color definitions to the light and dark variations */+@define-color alt_base_color mix(@theme_bg_color, @theme_base_color, 0.5);+@define-color alt_subdued_color mix(@theme_bg_color, @subdued_color, 0.5);++@define-color alt_border_color mix(@theme_tooltip_bg_color, @border_color, 0.5);+@define-color colored_border_color mix(@alt_border_color, shade(@theme_selected_bg_color, 0.5), 0.2);+@define-color focused_border_color mix(@internal_element_color, @theme_selected_bg_color, 0.8);+@define-color suggested_action_border_color mix(@alt_border_color, shade(@theme_selected_bg_color, 0.2), 0.2);+@define-color destructive_action_border_color mix(@alt_border_color, shade(@error_color, 0.2), 0.2);+@define-color insensitive_border_color alpha(@alt_border_color, 0.5);++/* +@define-color insensitive_fg_color alpha(@theme_fg_color, 0.5);+@define-color insensitive_internal_element_color alpha(@internal_element_color, 0.5);+@define-color selected_internal_element_color alpha(@theme_selected_fg_color, 0.6);+ */+@define-color insensitive_fg_color mix(@theme_fg_color, @theme_bg_color, 0.5);+@define-color insensitive_internal_element_color mix(@internal_element_color, @theme_bg_color, 0.5);+@define-color selected_internal_element_color mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.4);++@define-color button_top_color mix(@active_element, @theme_base_color, 0.7);+@define-color button_bottom_color mix(@active_element, @theme_bg_color, 0.7);+@define-color button_top_hover_color mix(@active_element, @theme_base_color, 0.6);+@define-color button_bottom_hover_color mix(@active_element, @theme_bg_color, 0.6);+@define-color button_top_active_color mix(@active_element, @theme_base_color, 0.5);+@define-color button_bottom_active_color mix(@active_element, @theme_bg_color, 0.5);+@define-color button_top_active_hover_color mix(@active_element, @theme_base_color, 0.4);+@define-color button_bottom_active_hover_color mix(@active_element, @theme_bg_color, 0.4);++@define-color colored_button_top_color mix(@button_top_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_bottom_color mix(@button_bottom_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_top_hover_color mix(@button_top_hover_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_bottom_hover_color mix(@button_bottom_hover_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_top_active_color mix(@button_top_active_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_bottom_active_color mix(@button_bottom_active_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_top_active_hover_color mix(@button_top_active_hover_color, @theme_selected_bg_color, 0.2);+@define-color colored_button_bottom_active_hover_color mix(@button_bottom_active_hover_color, @theme_selected_bg_color, 0.2);++@define-color suggested_action_button_top_color mix(@theme_bg_color, shade(@theme_selected_bg_color, 1.1), 0.8);+@define-color suggested_action_button_bottom_color mix(@theme_bg_color, shade(@theme_selected_bg_color, 0.9), 0.8);+@define-color suggested_action_button_top_hover_color mix(@theme_bg_color, shade(@theme_selected_bg_color, 1.2), 0.8);+@define-color suggested_action_button_bottom_hover_color mix(@theme_bg_color, shade(@theme_selected_bg_color, 1.0), 0.8);+@define-color suggested_action_button_top_active_color mix(@theme_bg_color, shade(@theme_selected_bg_color, 0.9), 0.8);+@define-color suggested_action_button_bottom_active_color mix(@theme_bg_color, shade(@theme_selected_bg_color, 1.0), 0.8);++@define-color destructive_action_button_top_color mix(@theme_bg_color, shade(@error_color, 1.1), 0.8);+@define-color destructive_action_button_bottom_color mix(@theme_bg_color, shade(@error_color, 0.9), 0.8);+@define-color destructive_action_button_top_hover_color mix(@theme_bg_color, shade(@error_color, 1.2), 0.8);+@define-color destructive_action_button_bottom_hover_color mix(@theme_bg_color, shade(@error_color, 1.0), 0.8);+@define-color destructive_action_button_top_active_color mix(@theme_bg_color, shade(@error_color, 0.9), 0.8);+@define-color destructive_action_button_bottom_active_color mix(@theme_bg_color, shade(@error_color, 1.0), 0.8);++/*****************+ * Fallback Mode *+ *****************/+@define-color os_chrome_bg_color black;+@define-color os_chrome_fg_color #ccc;+@define-color os_chrome_selected_bg_color #333;+@define-color os_chrome_selected_fg_color white;
+ app-data/themes/gtk/default/gtk-dark.css view
@@ -0,0 +1,36 @@+@import url("reset.css");++/* Dark color scheme */+@define-color theme_base_color #2a2f25;+@define-color active_element #caba9a;+@define-color theme_text_color #d0d5d0;+@define-color border_color #304020;+@define-color internal_element_color #cacdc6;++@define-color theme_selected_bg_color #658a60;+@define-color theme_selected_fg_color #ffffff;++@define-color link_color #729fcf;+@define-color info_color #c4a000;+@define-color warning_color #f57900;+@define-color question_color #ad7fa8;+@define-color error_color #ef2929;+@define-color other_color #c17d11;+++@define-color subdued_color shade(@theme_base_color, 0.3);+@define-color theme_bg_color #222320;+@define-color theme_fg_color @theme_text_color;+@define-color theme_tooltip_bg_color mix(@subdued_color, #000000, 0.5);+@define-color theme_tooltip_fg_color @theme_text_color;++@define-color placeholder_text_color @internal_element_color;++@import url("gtk-common.css");+@import url("gtk-widgets-assets-dark.css");+@import url("gtk-widgets-backgrounds-and-texts.css");+@import url("gtk-widgets-borders.css");+@import url("gtk-widgets.css");+@import url("app-specific.css");+@import url("keybindings.css");+
+ app-data/themes/gtk/default/gtk-fallback.css view
@@ -0,0 +1,15 @@+.menu {+ border-image: linear-gradient(to top,+ alpha(@border_color, 0.80),+ alpha(@border_color, 0.60) 33%,+ alpha(@border_color, 0.50) 66%,+ alpha(@border_color, 0.15)) 1 1 1 1/ 1px 1px 1px 1px;+}++.menubar .menu {+ border-image: linear-gradient(to top,+ alpha(@border_color, 0.80),+ alpha(@border_color, 0.60) 33%,+ alpha(@border_color, 0.50) 66%,+ transparent 99%) 1 1 1 1/ 1px 1px 1px 1px;+}
+ app-data/themes/gtk/default/gtk-widgets-assets-dark.css view
@@ -0,0 +1,339 @@+/****************+ * Content view *+ ****************/+.content-view.view {+ background-image: url("assets/noise-texture-dark.png");+}++/***************+ * Resize grip *+ ***************/+.grip {+ background-image: url("assets/resize-grip-dark.svg");+}++.grip:hover {+ background-image: url("assets/resize-grip-hover-dark.svg");+}++.grip:active {+ background-image: url("assets/resize-grip-active.svg");+}++/*******************+ * Pane separators *+ *******************/+.pane-separator {+ background-position: center;+ background-repeat: no-repeat;+ background-image: url("assets/pane-separator-grip-dark.svg");+}++.pane-separator:hover {+ background-image: url("assets/pane-separator-grip-hover-dark.svg");+}++.pane-separator:active {+ background-image: url("assets/pane-separator-grip-active.svg");+}++.pane-separator.vertical {+ background-image: url("assets/pane-separator-grip-vertical-dark.svg");+}++.pane-separator.vertical:hover {+ background-image: url("assets/pane-separator-grip-vertical-hover-dark.svg");+}++.pane-separator.vertical:active {+ background-image: url("assets/pane-separator-grip-vertical-active.svg");+}++/*************************+ * Check and Radio items *+ *************************/+.check:active,+.check row:active,+.view.cell.check:active {+ background-image: url("assets/check-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_color,+ @suggested_action_button_bottom_color+ );+ background-color: transparent;+}++.check:active:hover,+.check row:active:hover,+.view.cell.check:active:hover {+ background-image: url("assets/check-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_hover_color,+ @suggested_action_button_bottom_hover_color+ );+ background-color: transparent;+}++.check:active:insensitive,+.check row:active:insensitive,+.view.cell.check:active:insensitive {+ background-image: url("assets/check-insensitive-dark.svg");+ background-color: @theme_bg_color;+}++.radio:active,+.radio row:active,+.view.cell.radio:active {+ background-image: url("assets/radio-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_color,+ @suggested_action_button_bottom_color+ );+ background-color: transparent;+}++.radio:active:hover,+.radio row:active:hover,+.view.cell.radio:active:hover {+ background-image: url("assets/radio-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_hover_color,+ @suggested_action_button_bottom_hover_color+ );+ background-color: transparent;+}++.radio:active:insensitive,+.radio row:active:insensitive,+.view.cell.radio:active:insensitive {+ background-image: url("assets/radio-insensitive-dark.svg");+ background-color: @theme_bg_color;+}++.check:inconsistent,+.check row:inconsistent,+.view.cell.check:inconsistent,+.radio:inconsistent,+.radio row:inconsistent,+.view.cell.radio:inconsistent {+ background-image: url("assets/mix-dark.svg"),+ linear-gradient(to bottom,+ @colored_button_top_color,+ @colored_button_bottom_color+ );+ background-color: transparent;+}++.check:inconsistent:hover,+.check row:inconsistent:hover,+.view.cell.check:inconsistent:hover,+.radio:inconsistent:hover,+.radio row:inconsistent:hover,+.view.cell.radio:inconsistent:hover {+ background-image: url("assets/mix-dark.svg"),+ linear-gradient(to bottom,+ @colored_button_top_hover_color,+ @colored_button_bottom_hover_color+ );+ background-color: transparent;+}++.check:inconsistent:insensitive,+.check row:inconsistent:insensitive,+.view.cell.check:inconsistent:insensitive,+.radio:inconsistent:insensitive,+.radio row:inconsistent:insensitive,+.view.cell.radio:inconsistent:insensitive {+ background-image: url("assets/mix-insensitive-dark.svg");+ background-color: @theme_bg_color;+}++.menuitem.check:active {+ background-image: url("assets/check-dark.svg");+ background-color: transparent;+}++.menuitem.check:active:hover {+ background-image: url("assets/check-selected.svg");+ background-color: transparent;+}++.menuitem.check:active:insensitive {+ background-image: url("assets/check-insensitive-dark.svg");+ background-color: transparent;+}++.menuitem.radio:active {+ background-image: url("assets/radio-dark.svg");+ background-color: transparent;+}++.menuitem.radio:active:hover {+ background-image: url("assets/radio-selected.svg");+ background-color: transparent;+}++.menuitem.radio:active:insensitive {+ background-image: url("assets/radio-insensitive-dark.svg");+ background-color: transparent;+}++.menuitem.check:inconsistent,+.menuitem.radio:inconsistent {+ background-image: url("assets/mix-dark.svg");+ background-color: transparent;+}++.menuitem.check:inconsistent:hover,+.menuitem.radio:inconsistent:hover {+ background-image: url("assets/mix-selected.svg");+ background-color: transparent;+}++.menuitem.check:inconsistent:insensitive,+.menuitem.radio:inconsistent:insensitive {+ background-image: url("assets/mix-insensitive-dark.svg");+ background-color: transparent;+}++.sidebar .view.radio:hover,+.sidebar .view.radio:focus {+ background-image: url("assets/radio-hover-dark.svg");+ background-color: transparent;+}++.sidebar .view.radio:active,+.sidebar .view.radio:active:hover,+.sidebar .view.radio:active:focus {+ background-image: url("assets/radio-dark.svg");+ background-color: transparent;+}++.sidebar .view.radio:selected:hover,+.sidebar .view.radio:selected:focus {+ background-image: url("assets/radio-selected-hover.svg");+ background-color: transparent; +}++.sidebar .view.radio:selected:active,+.sidebar .view.radio:selected:active:hover,+.sidebar .view.radio:selected:active:focus {+ background-image: url("assets/radio-selected.svg");+ background-color: transparent;+}++/*********************+ * GtkScale's slider *+ *********************/+.scale.scale-has-marks-above.slider.horizontal {+ background-image: url("assets/scale-slider-up-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.horizontal:hover {+ background-image: url("assets/scale-slider-up-hover-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.horizontal:active {+ background-image: url("assets/scale-slider-up-active-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.fine-tune.horizontal:active {+ background-image: url("assets/scale-slider-up-fine-tune-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.horizontal:insensitive {+ background-image: url("assets/scale-slider-up-insensitive-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical {+ background-image: url("assets/scale-slider-left-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical:hover {+ background-image: url("assets/scale-slider-left-hover-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical:active {+ background-image: url("assets/scale-slider-left-active-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.fine-tune.vertical:active {+ background-image: url("assets/scale-slider-left-fine-tune-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical:insensitive {+ background-image: url("assets/scale-slider-left-insensitive-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal {+ background-image: url("assets/scale-slider-down-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal:hover {+ background-image: url("assets/scale-slider-down-hover-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal:active {+ background-image: url("assets/scale-slider-down-active-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.fine-tune.horizontal:active {+ background-image: url("assets/scale-slider-down-fine-tune-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal:insensitive {+ background-image: url("assets/scale-slider-down-insensitive-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical {+ background-image: url("assets/scale-slider-right-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical:hover {+ background-image: url("assets/scale-slider-right-hover-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical:active {+ background-image: url("assets/scale-slider-right-active-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.fine-tune.vertical:active {+ background-image: url("assets/scale-slider-right-fine-tune-dark.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical:insensitive {+ background-image: url("assets/scale-slider-right-insensitive-dark.svg");+ background-color: transparent;+}++/********************************+ * Touch text selection handles *+ ********************************/+.cursor-handle.bottom {+ background-image: url("assets/scale-slider-up-dark.svg");+ background-color: transparent;+}++.cursor-handle.top {+ background-image: url("assets/scale-slider-down-dark.svg");+ background-color: transparent;+}
+ app-data/themes/gtk/default/gtk-widgets-assets.css view
@@ -0,0 +1,339 @@+/****************+ * Content view *+ ****************/+.content-view.view {+ background-image: url("assets/noise-texture.png");+}++/***************+ * Resize grip *+ ***************/+.grip {+ background-image: url("assets/resize-grip.svg");+}++.grip:hover {+ background-image: url("assets/resize-grip-hover.svg");+}++.grip:active {+ background-image: url("assets/resize-grip-active.svg");+}++/*******************+ * Pane separators *+ *******************/+.pane-separator {+ background-position: center;+ background-repeat: no-repeat;+ background-image: url("assets/pane-separator-grip.svg");+}++.pane-separator:hover {+ background-image: url("assets/pane-separator-grip-hover.svg");+}++.pane-separator:active {+ background-image: url("assets/pane-separator-grip-active.svg");+}++.pane-separator.vertical {+ background-image: url("assets/pane-separator-grip-vertical.svg");+}++.pane-separator.vertical:hover {+ background-image: url("assets/pane-separator-grip-vertical-hover.svg");+}++.pane-separator.vertical:active {+ background-image: url("assets/pane-separator-grip-vertical-active.svg");+}++/*************************+ * Check and Radio items *+ *************************/+.check:active,+.check row:active,+.view.cell.check:active {+ background-image: url("assets/check-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_color,+ @suggested_action_button_bottom_color+ );+ background-color: transparent;+}++.check:active:hover,+.check row:active:hover,+.view.cell.check:active:hover {+ background-image: url("assets/check-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_hover_color,+ @suggested_action_button_bottom_hover_color+ );+ background-color: transparent;+}++.check:active:insensitive,+.check row:active:insensitive,+.view.cell.check:active:insensitive {+ background-image: url("assets/check-insensitive.svg");+ background-color: @theme_bg_color;+}++.radio:active,+.radio row:active,+.view.cell.radio:active {+ background-image: url("assets/radio-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_color,+ @suggested_action_button_bottom_color+ );+ background-color: transparent;+}++.radio:active:hover,+.radio row:active:hover,+.view.cell.radio:active:hover {+ background-image: url("assets/radio-selected.svg"),+ linear-gradient(to bottom,+ @suggested_action_button_top_hover_color,+ @suggested_action_button_bottom_hover_color+ );+ background-color: transparent;+}++.radio:active:insensitive,+.radio row:active:insensitive,+.view.cell.radio:active:insensitive {+ background-image: url("assets/radio-insensitive.svg");+ background-color: @theme_bg_color;+}++.check:inconsistent,+.check row:inconsistent,+.view.cell.check:inconsistent,+.radio:inconsistent,+.radio row:inconsistent,+.view.cell.radio:inconsistent {+ background-image: url("assets/mix.svg"),+ linear-gradient(to bottom,+ @colored_button_top_color,+ @colored_button_bottom_color+ );+ background-color: transparent;+}++.check:inconsistent:hover,+.check row:inconsistent:hover,+.view.cell.check:inconsistent:hover,+.radio:inconsistent:hover,+.radio row:inconsistent:hover,+.view.cell.radio:inconsistent:hover {+ background-image: url("assets/mix.svg"),+ linear-gradient(to bottom,+ @colored_button_top_hover_color,+ @colored_button_bottom_hover_color+ );+ background-color: transparent;+}++.check:inconsistent:insensitive,+.check row:inconsistent:insensitive,+.view.cell.check:inconsistent:insensitive,+.radio:inconsistent:insensitive,+.radio row:inconsistent:insensitive,+.view.cell.radio:inconsistent:insensitive {+ background-image: url("assets/mix-insensitive.svg");+ background-color: @theme_bg_color;+}++.menuitem.check:active {+ background-image: url("assets/check.svg");+ background-color: transparent;+}++.menuitem.check:active:hover {+ background-image: url("assets/check-selected.svg");+ background-color: transparent;+}++.menuitem.check:active:insensitive {+ background-image: url("assets/check-insensitive.svg");+ background-color: transparent;+}++.menuitem.radio:active {+ background-image: url("assets/radio.svg");+ background-color: transparent;+}++.menuitem.radio:active:hover {+ background-image: url("assets/radio-selected.svg");+ background-color: transparent;+}++.menuitem.radio:active:insensitive {+ background-image: url("assets/radio-insensitive.svg");+ background-color: transparent;+}++.menuitem.check:inconsistent,+.menuitem.radio:inconsistent {+ background-image: url("assets/mix.svg");+ background-color: transparent;+}++.menuitem.check:inconsistent:hover,+.menuitem.radio:inconsistent:hover {+ background-image: url("assets/mix-selected.svg");+ background-color: transparent;+}++.menuitem.check:inconsistent:insensitive,+.menuitem.radio:inconsistent:insensitive {+ background-image: url("assets/mix-insensitive.svg");+ background-color: transparent;+}++.sidebar .view.radio:hover,+.sidebar .view.radio:focus {+ background-image: url("assets/radio-hover.svg");+ background-color: transparent;+}++.sidebar .view.radio:active,+.sidebar .view.radio:active:hover,+.sidebar .view.radio:active:focus {+ background-image: url("assets/radio.svg");+ background-color: transparent;+}++.sidebar .view.radio:selected:hover,+.sidebar .view.radio:selected:focus {+ background-image: url("assets/radio-selected-hover.svg");+ background-color: transparent; +}++.sidebar .view.radio:selected:active,+.sidebar .view.radio:selected:active:hover,+.sidebar .view.radio:selected:active:focus {+ background-image: url("assets/radio-selected.svg");+ background-color: transparent;+}++/*********************+ * GtkScale's slider *+ *********************/+.scale.scale-has-marks-above.slider.horizontal {+ background-image: url("assets/scale-slider-up.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.horizontal:hover {+ background-image: url("assets/scale-slider-up-hover.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.horizontal:active {+ background-image: url("assets/scale-slider-up-active.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.fine-tune.horizontal:active {+ background-image: url("assets/scale-slider-up-fine-tune.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.horizontal:insensitive {+ background-image: url("assets/scale-slider-up-insensitive.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical {+ background-image: url("assets/scale-slider-left.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical:hover {+ background-image: url("assets/scale-slider-left-hover.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical:active {+ background-image: url("assets/scale-slider-left-active.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.fine-tune.vertical:active {+ background-image: url("assets/scale-slider-left-fine-tune.svg");+ background-color: transparent;+}++.scale.scale-has-marks-above.slider.vertical:insensitive {+ background-image: url("assets/scale-slider-left-insensitive.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal {+ background-image: url("assets/scale-slider-down.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal:hover {+ background-image: url("assets/scale-slider-down-hover.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal:active {+ background-image: url("assets/scale-slider-down-active.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.fine-tune.horizontal:active {+ background-image: url("assets/scale-slider-down-fine-tune.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.horizontal:insensitive {+ background-image: url("assets/scale-slider-down-insensitive.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical {+ background-image: url("assets/scale-slider-right.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical:hover {+ background-image: url("assets/scale-slider-right-hover.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical:active {+ background-image: url("assets/scale-slider-right-active.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.fine-tune.vertical:active {+ background-image: url("assets/scale-slider-right-fine-tune.svg");+ background-color: transparent;+}++.scale.scale-has-marks-below.slider.vertical:insensitive {+ background-image: url("assets/scale-slider-right-insensitive.svg");+ background-color: transparent;+}++/********************************+ * Touch text selection handles *+ ********************************/+.cursor-handle.bottom {+ background-image: url("assets/scale-slider-up.svg");+ background-color: transparent;+}++.cursor-handle.top {+ background-image: url("assets/scale-slider-down.svg");+ background-color: transparent;+}
+ app-data/themes/gtk/default/gtk-widgets-backgrounds-and-texts.css view
@@ -0,0 +1,486 @@+/* Button and slider background and text */+.button,+.toolbar .button.raised,+.toolbar .raised .button,+.primary-toolbar .button:focus,+.primary-toolbar .spinbutton .button,+.primary-toolbar GtkComboBox .button,+.primary-toolbar GtkComboBox.combobox-entry .button,+column-header.button,+column-header .button,+.scale.slider,+GtkSwitch.slider,+.scrollbar.slider,+.check,+.check row,+.view.cell.check,+.radio,+.radio row,+.view.cell.radio,+.notebook tab {+ background-image: linear-gradient(to bottom,+ @button_top_color,+ @button_bottom_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++.scrollbar.slider.vertical {+ background-image: linear-gradient(to bottom,+ @button_top_color,+ alpha(@button_top_color, 0) 8px+ ),+ linear-gradient(to top,+ @button_bottom_color,+ alpha(@button_bottom_color, 0) 8px+ );+ background-color: mix(@button_top_color, @button_bottom_color, 0.5);+}++/* Prelit button and slider background and text */+.button:hover,+.toolbar .button.raised:hover,+.toolbar .raised .button:hover,+.primary-toolbar .button:hover,+.primary-toolbar .spinbutton .button:hover,+.primary-toolbar GtkComboBox .button:hover,+.primary-toolbar GtkComboBox.combobox-entry .button:hover,+column-header.button:hover,+column-header .button:hover,+.scale.slider:hover,+GtkSwitch.slider:hover,+.scrollbar.slider:hover,+.check:hover,+.check row:hover,+.view.cell.check:hover,+.radio:hover,+.radio row:hover,+.view.cell.radio:hover,+.notebook tab:hover {+ background-image: linear-gradient(to bottom,+ @button_top_hover_color,+ @button_bottom_hover_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++.scrollbar.slider.vertical:hover {+ background-image: linear-gradient(to bottom,+ @button_top_hover_color,+ alpha(@button_top_hover_color, 0) 8px+ ),+ linear-gradient(to top,+ @button_bottom_hover_color,+ alpha(@button_bottom_hover_color, 0) 8px+ );+ background-color: mix(@button_top_hover_color, @button_bottom_hover_color, 0.5);+}++/* Pushed button and through background and text */+.button:active,+.toolbar .button.raised:active,+.toolbar .raised .button:active,+.primary-toolbar .button:active,+.primary-toolbar .spinbutton .button:active,+.primary-toolbar GtkComboBox .button:active,+.primary-toolbar GtkComboBox.combobox-entry .button:active,+column-header.button:active,+column-header .button:active,+column-header .button.dnd,+.trough,+.trough row,+.scale.trough,+GtkSwitch.trough,+.scrollbar.trough {+ background-image: linear-gradient(to bottom,+ @button_top_active_color,+ @button_bottom_active_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++.scrollbar.trough.vertical {+ background-image: linear-gradient(to bottom,+ @button_top_active_color,+ alpha(@button_top_active_color, 0) 8px+ ),+ linear-gradient(to top,+ @button_bottom_active_color,+ alpha(@button_bottom_active_color, 0) 8px+ );+ background-color: mix(@button_top_active_color, @button_bottom_active_color, 0.5);+}++.trough.vertical {+ background-image: linear-gradient(to bottom,+ @button_top_active_color,+ alpha(@button_top_active_color, 0) 9px+ ),+ linear-gradient(to top,+ @button_bottom_active_color,+ alpha(@button_bottom_active_color, 0) 9px+ );+ background-color: mix(@button_top_active_color, @button_bottom_active_color, 0.5);+}++.scale.trough.vertical {+ background-image: linear-gradient(to bottom,+ @button_top_active_color,+ alpha(@button_top_active_color, 0) 3px+ ),+ linear-gradient(to top,+ @button_bottom_active_color,+ alpha(@button_bottom_active_color, 0) 3px+ );+ background-color: mix(@button_top_active_color, @button_bottom_active_color, 0.5);+}++/* Prelit pushed button background and text */+.button:active:hover,+.toolbar .button.raised:active:hover,+.toolbar .raised .button:active:hover,+.primary-toolbar .button:active:hover,+.primary-toolbar .spinbutton .button:active:hover,+.primary-toolbar GtkComboBox .button:active:hover,+.primary-toolbar GtkComboBox.combobox-entry .button:active:hover,+column-header.button:active:hover,+column-header .button:active:hover {+ background-image: linear-gradient(to bottom,+ @button_top_active_hover_color,+ @button_bottom_active_hover_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++/* Colored button background and text */+.button.default,+.toolbar .button.raised.default,+.toolbar .raised .button.default,+.primary-toolbar .button.default:focus {+ background-image: linear-gradient(to bottom,+ @colored_button_top_color,+ @colored_button_bottom_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++/* Prelit colored button background and text */+.button.default:hover,+.toolbar .button.raised.default:hover,+.toolbar .raised .button.default:hover,+.primary-toolbar .button.default:hover,+.scale.slider.fine-tune:active,+.scrollbar.slider.fine-tune:active {+ background-image: linear-gradient(to bottom, + @colored_button_top_hover_color, + @colored_button_bottom_hover_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++.scrollbar.slider.fine-tune.vertical:active {+ background-image: linear-gradient(to bottom,+ @colored_button_top_hover_color,+ alpha(@colored_button_top_hover_color, 0) 8px+ ),+ linear-gradient(to top,+ @colored_button_bottom_hover_color,+ alpha(@colored_button_bottom_hover_color, 0) 8px+ );+ background-color: mix(@colored_button_top_hover_color, @colored_button_bottom_hover_color, 0.5);+}++/* Pushed colored button background and text */+.button.default:active,+.toolbar .button.raised.default:active,+.toolbar .raised .button.default:active,+.primary-toolbar .button.default:active {+ background-image: linear-gradient(to bottom, + @colored_button_top_active_color, + @colored_button_bottom_active_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++/* Prelit pushed colored button background and text */+.button.default:active:hover,+.toolbar .button.raised.default:active:hover,+.toolbar .raised .button.default:active:hover,+.primary-toolbar .button.default:active:hover {+ background-image: linear-gradient(to bottom, + @colored_button_top_active_hover_color, + @colored_button_bottom_active_hover_color+ );+ background-color: transparent;+ color: @theme_fg_color;+}++/* Suggested action button and progressbar background and text */+.suggested-action.button,+.primary-toolbar .suggested-action.button,+.selection-mode.toolbar GtkToolButton.suggested-action .button,+.progressbar,+.progressbar row,+.scale.progressbar {+ background-image: linear-gradient(to bottom,+ @suggested_action_button_top_color,+ @suggested_action_button_bottom_color+ );+ background-color: transparent;+ color: @theme_selected_fg_color;+}++.progressbar.vertical {+ background-image: linear-gradient(to bottom,+ @suggested_action_button_top_color,+ alpha(@suggested_action_button_top_color, 0) 9px+ ),+ linear-gradient(to top,+ @suggested_action_button_bottom_color,+ alpha(@suggested_action_button_bottom_color, 0) 9px+ );+ background-color: mix(@suggested_action_button_top_color, @suggested_action_button_bottom_color, 0.5);+}++.scale.progressbar.vertical {+ background-image: linear-gradient(to bottom,+ @suggested_action_button_top_color,+ alpha(@suggested_action_button_top_color, 0) 3px+ ),+ linear-gradient(to top,+ @suggested_action_button_bottom_color,+ alpha(@suggested_action_button_bottom_color, 0) 3px+ );+ background-color: mix(@suggested_action_button_top_color, @suggested_action_button_bottom_color, 0.5);+}++/* Prelit suggested action button background and text */+.suggested-action.button:hover,+.primary-toolbar .suggested-action.button:hover,+.selection-mode.toolbar GtkToolButton.suggested-action .button:hover {+ background-image: linear-gradient(to bottom, + @suggested_action_button_top_hover_color, + @suggested_action_button_bottom_hover_color+ );+ background-color: transparent;+ color: @theme_selected_fg_color;+}++/* Pushed suggested action button and highlit through background and text */+.suggested-action.button:active,+.primary-toolbar .suggested-action.button:active,+.selection-mode.toolbar GtkToolButton.suggested-action .button:active,+.scale.trough.highlight,+GtkSwitch.trough:active {+ background-image: linear-gradient(to bottom, + @suggested_action_button_top_active_color, + @suggested_action_button_bottom_active_color+ );+ background-color: transparent;+ color: @theme_selected_fg_color;+}++.scale.trough.highlight.vertical {+ background-image: linear-gradient(to bottom,+ @suggested_action_button_top_active_color,+ alpha(@suggested_action_button_top_active_color, 0) 3px+ ),+ linear-gradient(to top,+ @suggested_action_button_bottom_active_color,+ alpha(@suggested_action_button_bottom_active_color, 0) 3px+ );+ background-color: mix(@suggested_action_button_top_active_color, @suggested_action_button_bottom_active_color, 0.5);+}++/* Destructive action button background and text */+.destructive-action.button,+.primary-toolbar .destructive-action.button {+ background-image: linear-gradient(to bottom,+ @destructive_action_button_top_color,+ @destructive_action_button_bottom_color+ );+ background-color: transparent;+ color: @theme_selected_fg_color;+}++/* Prelit destructive action button background and text */+.destructive-action.button:hover,+.primary-toolbar .destructive-action.button:hover {+ background-image: linear-gradient(to bottom, + @destructive_action_button_top_hover_color, + @destructive_action_button_bottom_hover_color+ );+ background-color: transparent;+ color: @theme_selected_fg_color;+}++/* Pushed destructive action button background and text */+.destructive-action.button:active,+.primary-toolbar .destructive-action.button:active {+ background-image: linear-gradient(to bottom, + @destructive_action_button_top_active_color, + @destructive_action_button_bottom_active_color+ );+ background-color: transparent;+ color: @theme_selected_fg_color;+}++/* Insensitive button and slider background and text */+.button:insensitive,+.toolbar .button.raised:insensitive,+.toolbar .raised .button:insensitive,+.primary-toolbar .spinbutton .button:insensitive,+.primary-toolbar GtkComboBox .button:insensitive,+.primary-toolbar GtkComboBox.combobox-entry .button:insensitive,+column-header.button:insensitive,+column-header .button:insensitive,+.scale.slider:insensitive,+GtkSwitch.slider:insensitive,+.scrollbar.slider:insensitive,+.check:insensitive,+.check row:insensitive,+.view.cell.check:insensitive,+.radio:insensitive,+.radio row:insensitive,+.view.cell.radio:insensitive,+.notebook tab:insensitive,+.button.default:insensitive,+.toolbar .button.raised.default:insensitive,+.toolbar .raised .button.default:insensitive,+.suggested-action.button:insensitive,+.primary-toolbar .suggested-action.button:insensitive,+.selection-mode.toolbar GtkToolButton.suggested-action .button:insensitive,+.progressbar:insensitive,+.progressbar row:insensitive,+.scale.progressbar:insensitive,+.destructive-action.button:insensitive,+.primary-toolbar .destructive-action.button:insensitive {+ background-image: none;+ background-color: mix(@theme_bg_color, mix(@button_top_color, @button_bottom_color, 0.5), 0.5);+ color: @insensitive_fg_color;+}++/* Insensitive Pushed button and through background and text */+.button:active:insensitive,+.toolbar .button.raised:active:insensitive,+.toolbar .raised .button:active:insensitive,+.primary-toolbar .button:active:insensitive,+.primary-toolbar .spinbutton .button:active:insensitive,+.primary-toolbar GtkComboBox .button:active:insensitive,+.primary-toolbar GtkComboBox.combobox-entry .button:active:insensitive,+column-header.button:active:insensitive,+column-header .button:active:insensitive,+.trough:insensitive,+.trough row:insensitive,+.scale.trough:insensitive,+GtkSwitch.trough:insensitive,+.scrollbar.trough:insensitive,+.button.default:active:insensitive,+.toolbar .button.raised.default:active:insensitive,+.toolbar .raised .button.default:active:insensitive,+.primary-toolbar .button.default:active:insensitive,+.suggested-action.button:active:insensitive,+.primary-toolbar .suggested-action.button:active:insensitive,+.selection-mode.toolbar GtkToolButton.suggested-action .button:active:insensitive,+.scale.trough.highlight:insensitive,+GtkSwitch.trough:active:insensitive,+.destructive-action.button:active:insensitive,+.primary-toolbar .destructive-action.button:active:insensitive {+ background-image: none;+ background-color: mix(@theme_bg_color, mix(@button_top_active_color, @button_bottom_active_color, 0.5), 0.5);+ color: @insensitive_fg_color;+}++/* Active menu button and tab background and text */+.menubar .menuitem:hover,+.button.menuitem.menubar:active,+GtkMenuButton.button:active,+.toolbar GtkMenuButton.button.raised:active,+.toolbar .raised GtkMenuButton.button:active,+.primary-toolbar GtkMenuButton.button:active,+.selection-mode.toolbar .selection-menu.button:active,+.selection-mode.header-bar .selection-menu.button:active,+GtkComboBox .button:active,+GtkComboBox.combobox-entry .button:active,+.notebook tab:active {+ background-image: none;+ background-color: @theme_base_color;+ color: @theme_text_color;+}++/* Entry background and text */+.entry {+ background-image: linear-gradient(to bottom,+ alpha(@theme_tooltip_bg_color, 0.2),+ alpha(@theme_tooltip_bg_color, 0) 4px+ );+ background-color: @theme_base_color;+ color: @theme_text_color;+}++/* Insensitive entry background and text */+.entry:insensitive {+ background-image: none;+ background-color: @alt_base_color;+ color: @insensitive_fg_color;+}++/* Toolbar and header bar background */+.toolbar,+.header-bar {+ background-image: none;+ background-color: @theme_bg_color;+}++/* Unfocused window toolbar and header bar background */+.toolbar:backdrop,+.header-bar:backdrop {+ background-image: none;+ background-color: @theme_bg_color;+}++/* Selection mode toolbar and header bar background */+.selection-mode.header-bar {+ background-image: linear-gradient(to bottom,+ mix(@info_color, @button_top_color, 0.8),+ mix(@info_color, @theme_bg_color, 0.8)+ );+ background-color: transparent;+}++/* Unfocused window selection mode toolbar and header bar background */+.selection-mode.toolbar,+.selection-mode.toolbar:backdrop,+.selection-mode.header-bar:backdrop {+ background-image: none;+ background-color: mix(@info_color, @theme_bg_color, 0.8);+}++/* Primary and inline toolbars background */+.primary-toolbar .toolbar,+.primary-toolbar.toolbar,+.inline-toolbar.toolbar {+ background-image: linear-gradient(to bottom,+ mix(@subdued_color, @theme_tooltip_bg_color, 0.2),+ mix(@subdued_color, @theme_bg_color, 0.2)+ );+ background-color: transparent;+}++/* Unfocused window primary toolbar and insensitive inline toolbar background */+.primary-toolbar .toolbar:backdrop,+.primary-toolbar.toolbar:backdrop,+.inline-toolbar.toolbar:insensitive,+.primary-toolbar .toolbar.vertical,+.primary-toolbar.toolbar.vertical,+.inline-toolbar.toolbar.vertical {+ background-image: none;+ background-color: @subdued_color;+}
+ app-data/themes/gtk/default/gtk-widgets-borders.css view
@@ -0,0 +1,215 @@+/* Generic element borders */+.entry,+.button,+.toolbar .button.raised,+.toolbar .raised .button,+.primary-toolbar .button:hover,+.primary-toolbar .button:active,+.primary-toolbar .spinbutton .button,+.primary-toolbar GtkComboBox .button,+.primary-toolbar GtkComboBox.combobox-entry .button,+column-header.button,+column-header .button,+.scale.slider,+GtkSwitch.slider,+.trough,+.trough row,+.scale.trough,+GtkSwitch.trough,+.notebook tab {+ border-radius: 4px;+ border-width: 1px;+ border-style: solid;+ border-color: @alt_border_color;+}++.scrollbar.slider,+.scrollbar.trough,+.check,+.check row,+.view.cell.check,+.radio,+.radio row,+.view.cell.radio {+ box-shadow: inset 0 0 0 1px @alt_border_color;+}++/* Colored element borders */+.button.default,+.toolbar .button.raised.default,+.toolbar .raised .button.default,+.primary-toolbar .button.default:hover,+.primary-toolbar .button.default:active {+ border-radius: 4px;+ border-width: 1px;+ border-style: solid;+ border-color: @colored_border_color;+}++.check:inconsistent,+.check row:inconsistent,+.view.cell.check:inconsistent,+.radio:inconsistent,+.radio row:inconsistent,+.view.cell.radio:inconsistent {+ box-shadow: inset 0 0 0 1px @colored_border_color;+}++/* Suggested action buttons borders */+.suggested-action.button,+.primary-toolbar .suggested-action.button,+.selection-mode.toolbar GtkToolButton.suggested-action .button,+.progressbar,+.progressbar row,+.scale.progressbar,+.scale.trough.highlight,+GtkSwitch.trough:active {+ border-radius: 4px;+ border-width: 1px;+ border-style: solid;+ border-color: @suggested_action_border_color;+}++.check:active,+.check row:active,+.view.cell.check:active,+.radio:active,+.radio row:active,+.view.cell.radio:active {+ box-shadow: inset 0 0 0 1px @suggested_action_border_color;+}++/* Destructive action buttons borders */+.destructive-action.button,+.primary-toolbar .destructive-action.button {+ border-radius: 4px;+ border-width: 1px;+ border-style: solid;+ border-color: @destructive_action_border_color;+}++/* Focused element borders */+.entry:focus,+.button:focus,+.toolbar .button.raised:focus,+.toolbar .raised .button:focus,+.primary-toolbar .button:focus,+.primary-toolbar .spinbutton .button:focus,+.primary-toolbar GtkComboBox .button:focus,+.primary-toolbar GtkComboBox.combobox-entry .button:focus,+column-header.button:focus,+column-header .button:focus,+.scale.slider:active,+/* GtkSwitch.slider:active, */+.scale.trough:focus,+GtkSwitch.trough:focus,+.notebook tab:active:focus {+ border-color: @focused_border_color;+ box-shadow: inset 0 0 0 1px alpha(@focused_border_color, 0.2);+}++.scrollbar.slider:active,+.check:focus,+.check row:focus,+.view.cell.check:focus,+.radio:focus,+.radio row:focus,+.view.cell.radio:focus {+ box-shadow: inset 0 0 0 2px alpha(@focused_border_color, 0.2),+ inset 0 0 0 1px @focused_border_color;+}++/* Focused colored element borders */+.button.default:focus,+.toolbar .button.raised.default:focus,+.toolbar .raised .button.default:focus,+.primary-toolbar .button.default:focus,+.scale.slider.fine-tune:active {+ border-color: @focused_border_color;+ box-shadow: inset 0 0 0 1px alpha(@focused_border_color, 0.2);+}++.scrollbar.slider.fine-tune:active,+.check:inconsistent:focus,+.check row:inconsistent:focus,+.view.cell.check:inconsistent:focus,+.radio:inconsistent:focus,+.radio row:inconsistent:focus,+.view.cell.radio:inconsistent:focus {+ box-shadow: inset 0 0 0 2px alpha(@focused_border_color, 0.2),+ inset 0 0 0 1px @focused_border_color;+}++/* Focused suggested action buttons borders */+.suggested-action.button:focus,+.primary-toolbar .suggested-action.button:focus,+.selection-mode.toolbar GtkToolButton.suggested-action .button:focus,+.scale.progressbar:focus,+.scale.trough.highlight:focus,+GtkSwitch.trough:active:focus {+ border-color: @suggested_action_border_color;+ box-shadow: inset 0 0 0 1px alpha(@theme_selected_fg_color, 0.6);+}++.check:active:focus,+.check row:active:focus,+.view.cell.check:active:focus,+.radio:active:focus,+.radio row:active:focus,+.view.cell.radio:active:focus {+ box-shadow: inset 0 0 0 2px alpha(@theme_selected_fg_color, 0.6),+ inset 0 0 0 1px @suggested_action_border_color;+}++/* Focused destructive action buttons borders */+.destructive-action.button:focus,+.primary-toolbar .destructive-action.button:focus {+ border-color: @destructive_action_border_color;+ box-shadow: inset 0 0 0 1px alpha(@theme_selected_fg_color, 0.6);+}++/* Insensitive element borders */+.entry:insensitive,+.button:insensitive,+.toolbar .button.raised:insensitive,+.toolbar .raised .button:insensitive,+.primary-toolbar .button:active:insensitive,+.primary-toolbar .spinbutton .button:insensitive,+.primary-toolbar GtkComboBox .button:insensitive,+.primary-toolbar GtkComboBox.combobox-entry .button:insensitive,+column-header.button:insensitive,+column-header .button:insensitive,+.scale.slider:insensitive,+GtkSwitch.slider:insensitive,+.trough:insensitive,+.trough row:insensitive,+.scale.trough:insensitive,+GtkSwitch.trough:insensitive,+.notebook tab:insensitive,+.button.default:insensitive,+.toolbar .button.raised.default:insensitive,+.toolbar .raised .button.default:insensitive,+.primary-toolbar .button.default:active:insensitive,+.suggested-action.button:insensitive,+.primary-toolbar .suggested-action.button:insensitive,+.selection-mode.toolbar GtkToolButton.suggested-action .button:insensitive,+.progressbar:insensitive,+.progressbar row:insensitive,+.scale.progressbar:insensitive,+.scale.trough.highlight:insensitive,+GtkSwitch.trough:active:insensitive,+.destructive-action.button:insensitive,+.primary-toolbar .destructive-action.button:insensitive {+ border-color: @insensitive_border_color;+}++.scrollbar.slider:insensitive,+.scrollbar.trough:insensitive,+.check:insensitive,+.check row:insensitive,+.view.cell.check:insensitive,+.radio:insensitive,+.radio row:insensitive,+.view.cell.radio:insensitive {+ box-shadow: inset 0 0 0 1px @insensitive_border_color;+}
+ app-data/themes/gtk/default/gtk-widgets.css view
@@ -0,0 +1,2178 @@+* {+ padding: 0;+ background-clip: border-box;++ -GtkWidget-link-color: @link_color;+ -GtkWidget-visited-link-color: @link_color;+ -GtkIMHtml-hyperlink-color: @link_color;+ -GtkHTML-link-color: @link_color;++ -GtkTextView-error-underline-color: @error_color;++ -GtkPaned-handle-size: 4;++ -GtkWindow-resize-grip-width: 0;+ -GtkWindow-resize-grip-height: 0;++ -GtkCheckButton-indicator-size: 16;+ -GtkCheckMenuItem-indicator-size: 16;++ -GtkToolItemGroup-expander-size: 12;+ -GtkExpander-expander-size: 12;+ -GtkTreeView-expander-size: 12;++ /* The size for scrollbars. The slider is 2px smaller, but we keep it+ * up so that the whole area is sensitive to button presses for the+ * slider. The stepper button is larger in both directions, the slider+ * only in the width+ */+ -GtkScrolledWindow-scrollbar-spacing: 0;+ -GtkScrolledWindow-scrollbars-within-bevel: 1;++ -GtkToolButton-icon-spacing: 4;++ -GtkTreeView-horizontal-separator: 4;++ -GtkMenu-horizontal-padding: 0;+ -GtkMenu-vertical-padding: 0;++ -WnckTasklist-fade-overlay-rect: 0;++ -GtkWidget-focus-padding: 0;+ -GtkWidget-focus-line-width: 0;++ -GtkWidget-cursor-color: white;++ outline-offset: -3px;+ /* outline-radius: 4px; unsupported by older gtk */+ outline-style: dashed;+ outline-color: @internal_element_color;+}++/***************+ * Base States *+ ***************/+.background {+ background-color: @theme_bg_color;+ color: @theme_fg_color;+}++/* FIXME: why do we still need this? */+GtkClutterOffscreen {+ background-color: @theme_bg_color;+ color: @theme_fg_color;+}++*:insensitive {+ border-color: @insensitive_border_color;+ color: @insensitive_fg_color;+}++*:selected {+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++*:insensitive:selected {+ color: mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.5);+}++.gtkstyle-fallback {+ background-color: @theme_bg_color;+ color: @theme_fg_color;+}++.gtkstyle-fallback:hover {+ background-color: shade(@theme_bg_color, 1.1);+ color: @theme_fg_color;+}++.gtkstyle-fallback:active {+ background-color: shade(@theme_bg_color, 0.9);+ color: @theme_fg_color;+}++.gtkstyle-fallback:insensitive {+ background-color: @theme_bg_color;+ color: @insensitive_fg_color;+}++.gtkstyle-fallback:selected {+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++GtkImage,+GtkImage:insensitive,+GtkLabel,+GtkLabel:insensitive {+ background-color: transparent;+}++/*****************+ * Miscellaneous *+ *****************/+@keyframes spinner {+ 0.00% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)); }++ 12.5% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)); }++ 25.0% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)); }++ 37.5% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)); }++ 50.0% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)); }++ 62.5% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)); }++ 75.0% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)); }++ 87.5% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)); }++ 100% { background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)); }+}++.spinner {+ background-color: transparent;+ background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent));+ background-position: 14% 14%, 0% 50%, 14% 86%, 50% 100%, 86% 86%, 100% 50%, 86% 14%, 50% 0%;+ background-size: 20% 20%;+ background-repeat: no-repeat;+}++.spinner:active {+ background-image: -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.875)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.750)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.625)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.500)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.375)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.250)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(alpha(currentColor, 0.125)), to(transparent)),+ -gtk-gradient(radial, center center, 0, center center, 0.5, to(currentColor), to(transparent));+ animation: spinner 1s infinite linear;+}++.button .spinner:active {+ color: @theme_fg_color;+}++GtkStatusbar {+ -GtkStatusbar-shadow-type: none;++ padding: 3px;+ color: @theme_fg_color;+}++.rubberband,+.view.rubberband,+.content-view.view.rubberband {+ border-width: 1px;+ border-style: solid;+ border-color: alpha (@theme_selected_bg_color, 0.8);+ background-color: alpha (@theme_selected_bg_color, 0.2);+}++.dnd,+GtkTreeView.dnd {+ border-width: 2px;+ border-style: solid;+ border-color: @internal_element_color;+}++.separator,+GtkTreeView.separator,+GtkTreeView.view.separator {+ background-color: transparent;+ color: @insensitive_border_color;+}++.pane-separator {+ background-color: transparent;+ color: @internal_element_color;+}++.pane-separator:hover {+ color: @theme_fg_color;+}++.pane-separator:active {+ color: @theme_selected_bg_color;+}++.pane-separator:insensitive {+ color: @insensitive_internal_element_color;+}++.pane-separator:selected {+ color: @selected_internal_element_color;+}++.pane-separator:selected:hover {+ color: @theme_selected_fg_color;+}++.notebook .pane-separator {+ background-color: @theme_base_color;+}++/* Calendars */+GtkCalendar {+ padding: 2px;+}++GtkCalendar.view {+ padding: 2px;+}++GtkCalendar.header {+ border-radius: 0;+ border-style: none;+ background-color: @theme_bg_color;+}++GtkCalendar.button,+GtkCalendar.button:insensitive {+ background-image: none;+ background-color: transparent;+}++.highlight,+GtkCalendar.highlight {+ padding: 0;+ border-radius: 0;+ border-style: none;+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++/*******************+ * Symbolic images *+ *******************/+.image,+.image:focus {+ color: @internal_element_color;+}++.image:hover,+.image:focus:hover {+ color: @theme_fg_color;+}++.image:active,+.image:focus:active {+ color: @theme_selected_bg_color;+}++.image:insensitive {+ color: @insensitive_internal_element_color;+}++.image:selected {+ color: @selected_internal_element_color;+}++.image:selected:hover {+ color: @theme_selected_fg_color;+}++.image:insensitive:selected {+ color: mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.7);+}++.view.image,+.view.image:hover {+ color: @theme_fg_color;+}++.view.image:selected,+.view.image:selected:hover {+ color: @theme_selected_fg_color;+}++.view.image:insensitive:selected {+ color: mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.5);+}++/**************+ * Dim labels *+ **************/+.dim-label,+.view.dim-label {+ color: @internal_element_color;+}++.dim-label:selected,+.view.dim-label:selected {+ color: @selected_internal_element_color;+}++/**********+ * Frames *+ **********/+.frame,+GtkScrolledWindow.frame {+ padding: 0;+ border-width: 1px;+ border-style: solid;+ border-color: @border_color;+}++.frame:insensitive,+GtkScrolledWindow.frame:insensitive {+ border-color: @insensitive_border_color;+}++/* avoid double borders when a viewport is + * packed into a GtkScrolledWindow */+GtkScrolledWindow GtkViewport.frame {+ border-style: none;+}++/**************+ * GtkInfoBar *+ **************/+GtkInfoBar {+ border-style: none;+ color: @theme_fg_color;+}++.info {+ border-color: mix(shade(@info_color, 0.5), @border_color, 0.5);+ background-color: mix(@info_color, @theme_bg_color, 0.5);+}++.warning {+ border-color: mix(shade(@warning_color, 0.5), @border_color, 0.5);+ background-color: mix(@warning_color, @theme_bg_color, 0.5);+}++.question {+ border-color: mix(shade(@question_color, 0.5), @border_color, 0.5);+ background-color: mix(@question_color, @theme_bg_color, 0.5);+}++.error {+ border-color: mix(shade(@error_color, 0.5), @border_color, 0.5);+ background-color: mix(@error_color, @theme_bg_color, 0.5);+}++.other {+ border-color: mix(shade(@other_color, 0.5), @border_color, 0.5);+ background-color: mix(@other_color, @theme_bg_color, 0.5);+}++/*****************+ * Color Chooser *+ *****************/+GtkColorSwatch {+ border-radius: 0;+ box-shadow: inset 0 0 0 1px alpha(black, 0.5), inset 0 0 0 1px alpha(@alt_border_color, 0.5);+ background-color: transparent;+}++GtkColorSwatch.top {+ border-top-left-radius: 4px;+ border-top-right-radius: 4px;+}++GtkColorSwatch.bottom {+ border-bottom-right-radius: 4px;+ border-bottom-left-radius: 4px;+}++GtkColorSwatch.left,+GtkColorSwatch:first-child {+ border-top-left-radius: 4px;+ border-bottom-left-radius: 4px;+}++GtkColorSwatch.right,+GtkColorSwatch:last-child {+ border-top-right-radius: 4px;+ border-bottom-right-radius: 4px;+}++GtkColorSwatch:only-child {+ border-radius: 4px;+}++GtkColorEditor GtkColorSwatch {+ border-radius: 4px;+}++GtkColorSwatch.color-light:hover {+ background-image: -gtk-gradient(radial, 0.5 1.5, 0, 0.5 0.5, 1,+ color-stop (0.0, alpha(black, 0.5)),+ color-stop (0.5, alpha(black, 0))+ );+ background-color: transparent;+}++GtkColorSwatch.color-dark:hover {+ background-image: -gtk-gradient(radial, 0.5 1.5, 0, 0.5 0.5, 1,+ color-stop (0.0, alpha(white, 1)),+ color-stop (0.5, alpha(white, 0))+ );+ background-color: transparent;+}++GtkColorSwatch.color-light:selected:hover,+GtkColorSwatch.color-dark:selected:hover {+ background-image: none;+}++.color-active-badge,+.color-active-badge:selected {+ border-width: 2px;+ border-style: solid;+ background-color: transparent;+}++.color-active-badge.color-light {+ border-color: black;+ color: black;+}++.color-active-badge.color-dark {+ border-color: white;+ color: white;+}++GtkColorChooserWidget #add-color-button {+ background-image: linear-gradient(to bottom,+ alpha(@theme_base_color, 0.25),+ alpha(@theme_base_color, 0.25)+ ),+ linear-gradient(to bottom, alpha(lime, 0.75), alpha(lime, 0)),+ linear-gradient(to left, red, blue);+ background-color: transparent;+ color: alpha(white, 0.75);+}++GtkColorChooserWidget #add-color-button:hover {+ background-image: -gtk-gradient(radial, 0.5 1.5, 0, 0.5 0.5, 1,+ color-stop(0.0, alpha(white, 1)),+ color-stop(0.5, alpha(white, 0))+ ),+ linear-gradient(to bottom,+ alpha(@theme_base_color, 0.25),+ alpha(@theme_base_color, 0.25)+ ),+ linear-gradient(to bottom, alpha(lime, 0.75), alpha(lime, 0)),+ linear-gradient(to left, red, blue);+ background-color: transparent;+ color: alpha(white, 0.75);+}++/****************+ * Progress bar *+ ****************/+GtkProgressBar {+ -GtkProgressBar-min-horizontal-bar-height: 20;+ -GtkProgressBar-min-vertical-bar-width: 20;++ padding: 0; /* FIXME: this should really be a margin... */+}++.progressbar,+.progressbar row,+.trough,+.trough row {+ border-radius: 100px;+}++/* for progressbars in cell renderers */+.trough row {+ padding: 0;+}++.trough row:selected {+ color: @theme_fg_color;+}++/* level bars as used for password quality or remaining power */+GtkLevelBar {+ -GtkLevelBar-min-block-width: 32;+ -GtkLevelBar-min-block-height: 8;+}++GtkLevelBar.vertical {+ -GtkLevelBar-min-block-width: 8;+ -GtkLevelBar-min-block-height: 32;+}++.level-bar.trough {+ padding: 0;+ border-width: 1px 0;+ border-color: transparent;+ background-image: none;+ background-color: transparent;+}++.level-bar.indicator-continuous.fill-block {+ padding: 0;+}++.level-bar.indicator-discrete.fill-block.horizontal {+ margin: 0;+ border-radius: 0;+ border-left-width: 0;+}++.level-bar.indicator-discrete.fill-block.vertical {+ margin: 0;+ border-radius: 0;+ border-bottom-width: 0;+ border-left-width: 1px;+}++/* discrete indicator border rounding,+ uncomment when :nth-child will be working+ on the widget++.level-bar.indicator-discrete.fill-block.horizontal:first-child {+ border-radius: 100px 0 0 100px;+ border-left-width: 1px;+}++.level-bar.indicator-discrete.fill-block.horizontal:last-child {+ border-radius: 0 100px 100px 0;+}++.level-bar.indicator-discrete.fill-block.horizontal:only-child {+ border-radius: 100px;+ border-left-width: 1px;+}++.level-bar.indicator-discrete.fill-block.vertical:first-child {+ border-radius: 100px 100px 0 0;+}++.level-bar.indicator-discrete.fill-block.vertical:last-child {+ border-radius: 0 0 100px 100px;+ border-bottom-width: 1px;+}++.level-bar.indicator-discrete.fill-block.vertical:only-child {+ border-radius: 100px;+ border-bottom-width: 1px;+}++*/++.level-bar.fill-block {+ border-radius: 100px;+ border-width: 1px;+ border-style: solid;+ border-color: mix(@alt_border_color, shade(@info_color, 0.2), 0.2);+ background-image: linear-gradient(to bottom,+ mix(@theme_bg_color, shade(@info_color, 1.1), 0.8),+ alpha(mix(@theme_bg_color, shade(@info_color, 1.1), 0.8), 0) 3px+ ),+ linear-gradient(to top,+ mix(@theme_bg_color, shade(@info_color, 0.9), 0.8),+ alpha(mix(@theme_bg_color, shade(@info_color, 0.9), 0.8), 0) 3px+ );+ background-color: mix(mix(@theme_bg_color, shade(@info_color, 1.1), 0.8), mix(@theme_bg_color, shade(@info_color, 0.9), 0.8), 0.5);+}++.level-bar.fill-block.level-high {+ border-color: @suggested_action_border_color;+ background-image: linear-gradient(to bottom,+ @suggested_action_button_top_color,+ alpha(@suggested_action_button_top_color, 0) 3px+ ),+ linear-gradient(to top,+ @suggested_action_button_bottom_color,+ alpha(@suggested_action_button_bottom_color, 0) 3px+ );+ background-color: mix(@suggested_action_button_top_color, @suggested_action_button_bottom_color, 0.5);+}++.level-bar.fill-block.level-low {+ border-color: @destructive_action_border_color;+ background-image: linear-gradient(to bottom,+ @destructive_action_button_top_color,+ alpha(@destructive_action_button_top_color, 0) 3px+ ),+ linear-gradient(to top,+ @destructive_action_button_bottom_color,+ alpha(@destructive_action_button_bottom_color, 0) 3px+ );+ background-color: mix(@destructive_action_button_top_color, @destructive_action_button_bottom_color, 0.5);+}++.level-bar.fill-block.empty-fill-block {+ border-color: @alt_border_color;+ background-image: linear-gradient(to bottom,+ @button_top_active_color,+ alpha(@button_top_active_color, 0) 3px+ ),+ linear-gradient(to top,+ @button_bottom_active_color,+ alpha(@button_bottom_active_color, 0) 3px+ );+ background-color: mix(@button_top_active_color, @button_bottom_active_color, 0.5);+}++/************+ * GtkScale *+ ************/+.scale {+ -GtkScale-slider-length: 24;+ -GtkRange-slider-width: 24;+ -GtkRange-trough-border: 0;+}++.scale.slider {+ border-radius: 100px;+}++.scale.scale-has-marks-above.slider.horizontal,+.scale.scale-has-marks-above.slider.vertical,+.scale.scale-has-marks-below.slider.horizontal,+.scale.scale-has-marks-below.slider.vertical {+ border-style: none;+}++/* +.scale.scale-has-marks-above.slider.horizontal {+ transform: rotate(45deg);+ border-top-left-radius: 0;+}++.scale.scale-has-marks-above.slider.vertical {+ transform: rotate(45deg);+ border-bottom-left-radius: 0;+}++.scale.scale-has-marks-below.slider.horizontal {+ transform: rotate(45deg);+ border-bottom-right-radius: 0;+}++.scale.scale-has-marks-below.slider.vertical {+ transform: rotate(45deg);+ border-top-right-radius: 0;+}+ */++.scale.trough {+ margin: 8px 0;+}++.scale.trough.vertical {+ margin: 0 8px;+}++.scale.trough,+.scale.trough.vertical,+.scale.trough.highlight,+.scale.trough.highlight.vertical,+.scale.progressbar,+.scale.progressbar.vertical {+ border-radius: 100px;+}++.scale.mark.separator {+ color: @insensitive_border_color;+}++/**************+ * Scrollbars *+ **************/+.scrollbar {+ -GtkScrollbar-has-backward-stepper: false;+ -GtkScrollbar-has-forward-stepper: false;+ -GtkRange-slider-width: 12px;+ -GtkScrollbar-min-slider-length: 12px;+ -GtkRange-trough-border: 0;+ -GtkRange-stepper-spacing: 0;+ -GtkRange-trough-under-steppers: 1;++ background-clip: padding-box;+}++.scrollbar.slider,+.scrollbar.trough {+ border-radius: 100px;+ border-width: 2px;+ border-style: solid;+ border-color: transparent;+}++/* the small square between scrollbars!!! */+.scrollbars-junction {+}++.scrollbar.button {+ border-style: none;+ background-image: none;+ background-color: transparent;+}++.scrollbar.button {+ color: @internal_element_color;+}++.scrollbar.button:hover {+ color: @theme_fg_color;+}++.scrollbar.button:active {+ color: @theme_selected_bg_color;+}++.scrollbar.button:insensitive {+ color: @insensitive_internal_element_color;+}++/*************+ * GtkSwitch *+ *************/+GtkSwitch {+ -GtkSwitch-slider-height: 24;+}++GtkSwitch.slider {+ padding: 4px;+ border-radius: 100px;+}++/****************+ * Text Entries *+ ****************/+.entry {+ padding: 4px;+}++.entry.progressbar,+.entry.progressbar.pulse {+ margin: 3px;+ border-radius: 0;+ border-style: none;+ box-shadow: none;+ background-image: linear-gradient(to top,+ @theme_selected_bg_color 2px,+ transparent 2px+ );+ background-color: transparent;+}++.entry:selected {+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++/* needed for webkit/GtkStyle/Evolution compatibility */+GtkHTML:active,+.entry:active {+ background-color: @subdued_color;+ color: @theme_fg_color;+}++.cursor-handle.bottom,+.cursor-handle.top {+ border-style: none;+ /* background-image in assets */+}++/***********+ * Buttons *+ ***********/+.button {+ -GtkButton-image-spacing: 4;+ -GtkButton-interior-focus: true;+ -GtkButton-default-border: 0;+ -GtkButton-inner-border: 0;+}++.button,+.button.menuitem.menubar,+GtkColorButton.button {+ padding: 4px;+}++.button.text-button {+ padding: 4px 8px;+}++.button.image-button {+ padding: 7px;+}++.button .separator {+ color: @insensitive_border_color;+}++GtkLinkButton.button {+}++/* Remove borders and backgrounds from primary toolbar buttons */+.primary-toolbar .button,+.primary-toolbar .button:insensitive {+ border-color: transparent;+ background-image: none;+ background-color: transparent;+}++/* linked entries/buttons */++/* Middle button */+.linked .entry,+.linked .button,+.toolbar .button.raised.linked,+.toolbar .raised.linked .button,+.primary-toolbar .linked .button,+.inline-toolbar.toolbar .button,+.inline-toolbar.toolbar GtkToolButton .button,+.osd.toolbar .button {+ border-radius: 0;+ border-left-width: 0;+}++/* Leftmost button */+.linked .entry:first-child,+.linked .button:first-child,+.toolbar .button.raised.linked:first-child,+.toolbar .raised.linked .button:first-child,+.primary-toolbar .linked .button:first-child,+.inline-toolbar.toolbar .button:first-child,+.inline-toolbar.toolbar GtkToolButton:first-child .button,+.osd.toolbar .button:first-child {+ border-radius: 4px 0 0 4px;+ border-left-width: 1px;+}++/* Rightmost button */+.linked .entry:last-child,+.linked .button:last-child,+.toolbar .button.raised.linked:last-child,+.toolbar .raised.linked .button:last-child,+.primary-toolbar .linked .button:last-child,+.inline-toolbar.toolbar .button:last-child,+.inline-toolbar.toolbar GtkToolButton:last-child .button,+.osd.toolbar .button:last-child {+ border-radius: 0 4px 4px 0;+}++/* Single button */+.linked .entry:only-child,+.linked .button:only-child,+.toolbar .button.raised.linked:only-child,+.toolbar .raised.linked .button:only-child,+.primary-toolbar .linked .button:only-child,+.inline-toolbar.toolbar .button:only-child,+.inline-toolbar.toolbar GtkToolButton:only-child .button,+.osd.toolbar .button:only-child {+ border-radius: 4px;+ border-left-width: 1px;+}++/* Middle button (vertical) */+.linked.vertical .entry,+.linked.vertical .button,+.inline-toolbar.toolbar.vertical .button,+.inline-toolbar.toolbar.vertical GtkToolButton .button {+ border-radius: 0;+ border-bottom-width: 0;+ border-left-width: 1px;+}++/* Topmost button (vertical) */+.linked.vertical .entry:first-child,+.linked.vertical .button:first-child,+.inline-toolbar.toolbar.vertical .button:first-child,+.inline-toolbar.toolbar.vertical GtkToolButton:first-child .button {+ border-radius: 4px 4px 0 0;+}++/* Bottommost button (vertical) */+.linked.vertical .entry:last-child,+.linked.vertical .button:last-child,+.inline-toolbar.toolbar.vertical .button:last-child,+.inline-toolbar.toolbar.vertical GtkToolButton:last-child .button {+ border-radius: 0 0 4px 4px;+ border-bottom-width: 1px;+}++/* Single button (vertical) */+.linked.vertical .entry:only-child,+.linked.vertical .button:only-child,+.inline-toolbar.toolbar.vertical .button:only-child,+.inline-toolbar.toolbar.vertical GtkToolButton:only-child .button {+ border-radius: 4px;+ border-bottom-width: 1px;+}++/* Special-case GtkMenuToolButton, since it's a GtkToolButton, but it+ * has a box inside to pack the button and the actual menu */+.inline-toolbar.toolbar GtkMenuToolButton .button:first-child,+.inline-toolbar.toolbar GtkMenuToolButton .button:last-child {+ border-radius: 0;+ border-left-width: 0;+}++.inline-toolbar.toolbar GtkMenuToolButton:first-child .button:first-child {+ border-radius: 4px 0 0 4px;+ border-left-width: 1px;+}++.inline-toolbar.toolbar GtkMenuToolButton:last-child .button:last-child {+ border-radius: 0 4px 4px 0;+}++.osd.toolbar GtkToolButton .button,+.osd.toolbar GtkToolButton:first-child .button,+.osd.toolbar GtkToolButton:last-child .button,+.osd.toolbar GtkToolButton:only-child .button {+ border-radius: 4px;+ border-width: 1px;+}++/****************+ * Radiobuttons *+ ****************/+.check {+ border-radius: 0;+}++.radio {+ border-radius: 100px;+}++.check:insensitive,+.radio:insensitive {+ background-image: linear-gradient(to bottom, transparent, transparent);+}++GtkCheckButton:hover,+GtkCheckButton:active:hover,+GtkCheckButton:selected {+ background-color: transparent;+}++/*****************+ * GtkSpinButton *+ *****************/+.spinbutton .button {+ padding-right: 6px;+ padding-left: 7px;+ border-radius: 0;+ border-width: 0 0 0 1px;+}++.spinbutton .button:first-child {+ border-radius: 4px 0 0 4px;+}++.spinbutton .button:last-child {+ border-radius: 0 4px 4px 0;+}++.spinbutton .button:dir(rtl) {+ border-width: 0 1px 0 0;+}++.spinbutton.vertical.entry {+ border-radius: 0;+}++.spinbutton.vertical .button {+ padding: 5px;+}++.spinbutton.vertical .button:first-child {+ border-radius: 4px 4px 0 0;+ border-width: 1px 1px 0 1px;+}++.spinbutton.vertical .button:last-child {+ border-radius: 0 0 4px 4px;+ border-width: 0 1px 1px 1px;+}++.spinbutton.vertical .button,+/* :active:active to override the dark overriden style for+ normal spinbutton buttons, yeah we lack !important */+.spinbutton.vertical .button:active:active {+}++/* :insensitive:insensitive to override the dark overriden style for+ normal spinbutton buttons, yeah we lack !important */+.spinbutton.vertical .button:insensitive:insensitive {+}++/**************+ * ComboBoxes *+ **************/+GtkComboBox {+ -GtkComboBox-arrow-scaling: 0.5;+ -GtkComboBox-shadow-type: none;++ padding: 0;+}++GtkComboBox .separator {+ /* always disable separators */+ -GtkWidget-wide-separators: true;+ -GtkWidget-horizontal-separator: 0;+ -GtkWidget-vertical-separator: 0;+}++GtkComboBox .button {+ padding: 2px;+}++GtkComboBox.combobox-entry .button {+ padding: 7px;+}++GtkComboBox.combobox-entry .entry:first-child,+GtkComboBox.combobox-entry .button:first-child {+ border-radius: 4px 0 0 4px;+}++GtkComboBox.combobox-entry .entry:last-child,+GtkComboBox.combobox-entry .button:last-child {+ border-radius: 0 4px 4px 0;+ border-left-width: 0;+}++/***************+ * Menu Button *+ ***************/+.selection-mode.toolbar .selection-menu.button,+.selection-mode.header-bar .selection-menu.button {+ border-color: transparent;+ background-image: none;+ background-color: transparent;+}++.selection-mode.toolbar .selection-menu.button:hover,+.selection-mode.header-bar .selection-menu.button:hover {+ border-color: @alt_border_color;+ background-image: linear-gradient(to bottom,+ @button_top_hover_color,+ @button_bottom_hover_color+ );+ background-color: transparent;+}++GtkComboBox.combobox-entry .button:active,+.linked GtkMenuButton.button:active,+.toolbar GtkMenuButton.button.raised.linked:active,+.toolbar .raised.linked GtkMenuButton.button:active,+.primary-toolbar .linked GtkMenuButton.button:active {+ border-radius: 0;+ border-left-width: 0;+ border-bottom-color: transparent;+}++GtkComboBox.combobox-entry .button:active:first-child,+.linked GtkMenuButton.button:active:first-child,+.toolbar GtkMenuButton.button.raised.linked:active:first-child,+.toolbar .raised.linked GtkMenuButton.button:active:first-child,+.primary-toolbar .linked GtkMenuButton.button:active:first-child {+ border-radius: 4px 0 0 0;+ border-left-width: 1px;+}++GtkComboBox.combobox-entry .button:active:last-child,+.linked GtkMenuButton.button:active:last-child,+.toolbar GtkMenuButton.button.raised.linked:active:last-child,+.toolbar .raised.linked GtkMenuButton.button:active:last-child,+.primary-toolbar .linked GtkMenuButton.button:active:last-child {+ border-radius: 0 4px 0 0;+}++.menubar .menuitem:hover, /* remove the image from the prelight areas */+.button.menuitem.menubar:active,+GtkMenuButton.button:active,+.toolbar GtkMenuButton.button.raised:active,+.toolbar .raised GtkMenuButton.button:active,+.primary-toolbar GtkMenuButton.button:active,+.selection-mode.toolbar .selection-menu.button:active,+.selection-mode.header-bar .selection-menu.button:active,+.linked GtkMenuButton.button:active:only-child,+.toolbar GtkMenuButton.button.raised.linked:active:only-child,+.toolbar .raised.linked GtkMenuButton.button:active:only-child,+.primary-toolbar .linked GtkMenuButton.button:active:only-child {+ border-radius: 4px 4px 0 0;+ border-width: 1px;+ border-style: solid;+ border-color: @alt_border_color;+ border-bottom-color: transparent;+}++/*********+ * Menus *+ *********/+.context-menu {+ font: initial;+}++.menu {+ padding: 1px;+ border-width: 1px;+ border-style: solid;+ border-color: @alt_border_color;+ background-color: @theme_base_color;+ color: @theme_text_color;+}++.menubar .menu,+.button.menubar .menu,+GtkMenuButton .menu,+.selection-mode.toolbar .selection-menu .menu,+.selection-mode.header-bar .selection-menu .menu,+GtkComboBox.combobox-entry .menu {+ padding-top: 0;+ border-top-width: 0;+}++.menu.button,+.primary-toolbar .menu.button {+ border-style: none;+ background-image: none;+ background-color: @theme_base_color;+ color: @internal_element_color;+}++.menu.button:hover,+.primary-toolbar .menu.button:hover {+ border-style: none;+ background-image: none;+ background-color: @theme_base_color;+ color: @theme_fg_color;+}++.menu.button:insensitive,+.primary-toolbar .menu.button:insensitive {+ border-style: none;+ background-image: none;+ background-color: @theme_base_color;+ color: @insensitive_internal_element_color;+}++.menu .menuitem,+.menubar .menu .menuitem,+.button .menu .menuitem {+ -GtkMenuItem-arrow-scaling: 0.5;++ padding: 3px 4px;+}++.menu .menuitem:hover {+ border-radius: 0;+ border-style: none;+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++.menu .menuitem:insensitive {+ background-color: @theme_base_color;+}++.menu .menuitem *:insensitive {+ color: @insensitive_fg_color;+}++.menuitem .accelerator {+ color: @internal_element_color;+}++.menuitem .accelerator:hover {+ color: @selected_internal_element_color;+}++.menuitem .accelerator:insensitive {+ color: @insensitive_internal_element_color;+}++.menuitem.arrow {+ color: @theme_text_color;+}++.menuitem.arrow:hover {+ color: @theme_selected_fg_color;+}++.menuitem.arrow:insensitive {+ color: @insensitive_fg_color;+}++.menuitem.separator {+ -GtkMenuItem-horizontal-padding: 0;++ color: @insensitive_border_color;+}++.menuitem.check,+.menuitem.check:active,+.menuitem.check:insensitive,+.menuitem.radio,+.menuitem.radio:active,+.menuitem.radio:insensitive {+ box-shadow: none;+}++.menuitem.check,+.menuitem.check:hover,+.menuitem.check:insensitive,+.menuitem.radio,+.menuitem.radio:hover,+.menuitem.radio:insensitive {+ background-image: none;+ background-color: transparent;+}++/* this controls the general appearance of the menubar */+.menubar {+ -GtkWidget-window-dragging: true;++ border-style: none;+}++.menubar .menuitem {+ padding: 3px 8px;+}++/* combobox menus */+GtkTreeMenu.menu {+ background-color: @theme_base_color;+}++GtkTreeMenu.menu .menuitem {+ padding: 4px 2px 2px 2px;+ color: @theme_text_color;+}++/**********************+ * Notebooks and tabs *+ **********************/+.notebook {+ engine: none;++ -GtkNotebook-initial-gap: 4;+ -GtkNotebook-tab-overlap: 1;+ -GtkNotebook-tab-curvature: 0;++ padding: 0;+ border-width: 1px;+ border-style: solid;+ border-color: @border_color;+ background-color: @theme_base_color;+}++.notebook:insensitive {+ border-color: @insensitive_border_color;+}++.notebook GtkViewport {+ background-color: @theme_base_color;+}++.notebook tab {+ padding: 5px 9px;+}++.notebook tab.top {+ border-radius: 0;+ border-width: 1px 1px 0 1px;+}++.notebook tab:first-child.top {+ border-top-left-radius: 4px;+}++.notebook tab:last-child.top {+ border-top-right-radius: 4px;+}++.notebook tab.top:active:focus {+/* + border-image-slice: 1;+ border-image-source: linear-gradient(to bottom, @focused_border_color, @border_color);+ */+ box-shadow: inset 0 1px alpha(@focused_border_color, 0.2),+ inset -1px 0 alpha(@focused_border_color, 0.1),+ inset 1px 0 alpha(@focused_border_color, 0.1);+}++.notebook tab.right {+ border-radius: 0;+ border-width: 1px 1px 1px 0;+}++.notebook tab:first-child.right {+ border-top-right-radius: 4px;+}++.notebook tab:last-child.right {+ border-bottom-right-radius: 4px;+}++.notebook tab.right:active:focus {+/* + border-image-slice: 1;+ border-image-source: linear-gradient(to left, @focused_border_color, @border_color);+ */+ box-shadow: inset -1px 0 alpha(@focused_border_color, 0.2),+ inset 0 1px alpha(@focused_border_color, 0.1),+ inset 0 -1px alpha(@focused_border_color, 0.1);+}++.notebook tab.bottom {+ border-radius: 0;+ border-width: 0 1px 1px 1px;+}++.notebook tab:first-child.bottom {+ border-bottom-left-radius: 4px;+}++.notebook tab:last-child.bottom {+ border-bottom-right-radius: 4px;+}++.notebook tab.bottom:active:focus {+/* + border-image-slice: 1;+ border-image-source: linear-gradient(to top, @focused_border_color, @border_color);+ */+ box-shadow: inset 0 -1px alpha(@focused_border_color, 0.2),+ inset -1px 0 alpha(@focused_border_color, 0.1),+ inset 1px 0 alpha(@focused_border_color, 0.1);+}++.notebook tab.left {+ border-radius: 0;+ border-width: 1px 0 1px 1px;+}++.notebook tab:first-child.left {+ border-top-left-radius: 4px;+}++.notebook tab:last-child.left {+ border-bottom-left-radius: 4px;+}++.notebook tab.left:active:focus {+/* + border-image-slice: 1;+ border-image-source: linear-gradient(to right, @focused_border_color, @border_color);+ */+ box-shadow: inset 1px 0 alpha(@focused_border_color, 0.2),+ inset 0 1px alpha(@focused_border_color, 0.1),+ inset 0 -1px alpha(@focused_border_color, 0.1);+}++/* close button styling */+.notebook tab .button,+.notebook tab .button:hover,+.notebook tab .button:active {+ border-style: none;+ background-image: none;+ background-color: transparent;+}++.notebook tab .button {+ color: @internal_element_color;+}++.notebook tab .button:hover {+ color: @theme_fg_color;+}++.notebook tab .button:active {+ color: @theme_selected_bg_color;+}++/************+ * Toolbars *+ ************/+.toolbar {+ padding: 6px;+ border-width: 0;+ border-style: solid;+ border-color: @border_color;+ color: @theme_fg_color;+}++.toolbar:insensitive {+ color: @insensitive_fg_color;+}++.toolbar .separator {+ color: @insensitive_border_color;+}++.toolbar .button {+ padding: 3px;+}++.toolbar .button.text-button {+ padding: 4px 16px;+}++.toolbar .button.image-button {+ padding: 7px;+}++/********************+ * Menubar Toolbars *+ ********************/+.toolbar.menubar {+ -GtkToolbar-button-relief: normal;+}++/***************+ * Header bars *+ ***************/+.header-bar {+ padding: 6px;+ border-width: 0 0 1px 0;+ border-style: solid;+ border-color: @border_color;+}++.header-bar:backdrop {+ color: @internal_element_color;+}++.header-bar .button.text-button {+ padding: 4px 16px;+}++.header-bar .button.image-button {+ padding: 7px;+}++.header-bar .title {+ font: Bold 11;+}++.header-bar .subtitle {+ font: 9;+}++/********************+ * Primary Toolbars *+ ********************/+/* applications using EggEditableToolbar usually set the primary-toolbar+ * hint on the containing vbox, so we need to handle both these cases here.+ */+.primary-toolbar .toolbar,+.primary-toolbar.toolbar {+ -GtkWidget-window-dragging: true;+ -GtkToolbar-button-relief: normal;++ padding-top: 3px;+ padding-bottom: 3px;+ border-width: 1px 0;+ border-style: solid;+ border-color: @border_color;+}++/*******************+ * Inline toolbars *+ *******************/+.inline-toolbar.toolbar {+ -GtkToolbar-button-relief: normal;++ padding: 3px;+ border-width: 1px;+ border-style: solid;+ border-color: @border_color;+}++.inline-toolbar.toolbar:insensitive {+ border-color: @insensitive_border_color;+}++.inline-toolbar.toolbar:last-child {+ border-top-width: 0;+}++.inline-toolbar.toolbar.vertical:last-child {+ border-left-width: 0;+}++.inline-toolbar.toolbar .button {+ padding: 7px;+}++/***********+ * Sidebar *+ ***********/+.sidebar,+.sidebar .view,+.sidebar GtkScrolledWindow {+ background-color: @alt_subdued_color;+}++.sidebar .view:hover {+ background-color: @subdued_color;+}++.sidebar .view:selected {+ background-color: @theme_selected_bg_color;+}++.sidebar .view.radio,+.sidebar .view.radio:active,+.sidebar .view.radio:focus,+.sidebar .view.radio:active:focus {+ box-shadow: none;+}++.sidebar .view.radio,+.sidebar .view.radio:selected {+ background-image: none;+ background-color: transparent;+}++/****************+ * GtkAssistant *+ ****************/+GtkAssistant .sidebar {+ padding: 12px;+ border-width: 1px;+ border-style: solid;+ border-color: @border_color;+ background-color: @alt_subdued_color;+ color: @internal_element_color;+ /* shall we make it like sidebars in general? */+}++GtkAssistant .sidebar .highlight {+ background-color: transparent;+ color: @theme_fg_color;+ font: bold;+}++/***********************+ * Tree and Icon views *+ ***********************/+GtkTreeView {+ -GtkTreeView-vertical-separator: 0;+}++GtkIconView.cell:selected {+ /* FIXME: this probably needs to be better;+ * see https://bugzilla.gnome.org/show_bug.cgi?id=644157+ */+ -GtkWidget-focus-padding: 1;+ -GtkWidget-focus-line-width: 1;++ border-radius: 8px;+}++GtkTreeView:selected:focus,+GtkIconView.cell:selected:focus {+ outline-color: @selected_internal_element_color;+}++GtkTreeView.cell {+ padding: 2px;+}++GtkTreeView.cell:hover {+ background-color: @alt_base_color;+ color: @theme_selected_fg_color;+}++.cell:insensitive {+ color: @insensitive_fg_color;+}++.cell:selected, row:selected, .cell:hover:selected {+ background-color: @theme_selected_bg_color;+ border-width: 0;+ border-radius: 3px;+ color: @theme_selected_fg_color;+ box-shadow: inset 0px 0px 3px mix(@theme_base_color, @theme_selected_bg_color, 0.4);+}++.cell:insensitive:selected {+ color: mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.5);+}++column-header.button,+column-header .button {+ padding: 2px 4px;+ border-radius: 0;+ border-width: 0 1px 1px 0;+}++column-header.button:last-child,+column-header:last-child .button {+ border-right-width: 0;+}++column-header .button.dnd {+ border-width: 0 1px 1px 1px;+}++.expander,+.expander:active {+ border-color: @internal_element_color;+ color: @internal_element_color;+}++.expander:hover,+.expander:active:hover {+ border-color: @theme_fg_color;+ color: @theme_fg_color;+}++.expander:insensitive,+.expander:active:insensitive {+ border-color: @insensitive_internal_element_color;+ color: @insensitive_internal_element_color;+}++.expander:focus,+.expander:active:focus {+ border-color: @theme_selected_bg_color;+}++.expander row:selected,+.expander row:active:selected {+ border-color: @selected_internal_element_color;+ color: @selected_internal_element_color;+}++.expander row:selected:hover,+.expander row:active:selected:hover {+ border-color: @theme_selected_fg_color;+ color: @theme_selected_fg_color;+}++.expander row:insensitive:selected,+.expander row:active:insensitive:selected {+ border-color: mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.7);+ color: mix(@theme_selected_fg_color, @theme_selected_bg_color, 0.7);+}++/**************+ * List boxes *+ **************/+.list-row,+EggListBox {+ -GtkWidget-focus-padding: 1;+ -GtkWidget-focus-line-width: 1;+}++.list,+EggListBox {+ background-color: @theme_base_color;+ color: @theme_text_color;+}++.list-row:hover,+EggListBox:hover {+ background-color: @alt_base_color;+}++.list-row:insensitive,+EggListBox:insensitive {+ background-color: @alt_base_color;+ color: @insensitive_fg_color;+}++.list-row:selected,+EggListBox:selected {+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++.list-row:selected:focus,+EggListBox:selected:focus {+ outline-color: @selected_internal_element_color;+}++/****************+ * Content view *+ ****************/+/* FIXME: EggListBox should set the .cell style class on+ * the background it renders for the children, like+ * GtkIconView and GtkTreeView do */+.content-view.view,+.content-view.cell {+ background-color: @alt_base_color;+ color: @theme_fg_color;+}++.content-view.view:hover,+.content-view.cell:hover,+EggListBox.content-view:hover {+ background-color: @theme_bg_color;+}++.content-view.view:insensitive,+.content-view.cell:insensitive,+EggListBox.content-view:insensitive {+ color: @insensitive_fg_color;+}++.content-view.view:active,+.content-view.view:selected,+.content-view.cell:active,+.content-view.cell:selected,+EggListBox.content-view:active,+EggListBox.content-view:selected {+ background-image: none;+ background-color: @theme_selected_bg_color;+ color: @theme_selected_fg_color;+}++GdMainIconView.content-view {+ -GdMainIconView-icon-size: 40;+}++GtkIconView.content-view.cell.check {+ opacity: 0.9;+ background-size: contain;+}++GtkIconView.content-view.check:hover,+GtkIconView.content-view.check:insensitive,+GtkIconView.content-view.check:selected {+ background-color: transparent;+}++.content-view.view.check,+.content-view.view.check:active {+ background-color: transparent;+}++.content-view.view .separator {+ color: @insensitive_border_color;+}++/* used by Documents and Evince */+.content-view.document-page {+ border-image: url("assets/thumbnail-frame.png") 3 3 6 4;+ border-width: 3px 3px 6px 4px;+ border-style: solid;+}++/************+ * Tooltips *+ ************/+.tooltip {+ opacity: 0.9;+ padding: 5px;+ border-radius: 4px;+ background-color: alpha(@theme_tooltip_bg_color, 0.9);+ color: alpha(@theme_tooltip_fg_color, 0.9);+}++/*****************+ * Floating bars *+ *****************/+.floating-bar {+ opacity: 0.9;+ padding: 3px;+ border-radius: 4px;+ background-color: @theme_tooltip_bg_color;+ color: @theme_tooltip_fg_color;+}++.floating-bar.top {+ border-top-left-radius: 0;+ border-top-right-radius: 0;+}++.floating-bar.right {+ border-top-right-radius: 0;+ border-bottom-right-radius: 0;+}++.floating-bar.bottom {+ border-bottom-right-radius: 0;+ border-bottom-left-radius: 0;+}++.floating-bar.left {+ border-top-left-radius: 0;+ border-bottom-left-radius: 0;+}++/*********************+ * App Notifications *+ *********************/+.app-notification {+ opacity: 0.9;+ padding: 8px;+ border-radius: 0 0 8px 8px;+ background-color: @theme_tooltip_bg_color;+ color: @theme_tooltip_fg_color;+}++/*******+ * OSD *+ *******/+.osd {+ opacity: 0.9;+}++.background.osd {+ background-color: @theme_tooltip_bg_color;+ color: @theme_tooltip_fg_color;+}++GtkOverlay.osd {+ background-color: transparent;+}++.osd.frame {+ background-clip: border-box;+ background-origin: border-box;+}++.osd .button {+ padding: 7px;+}++.osd.button {+ padding: 11px;+}++.osd.toolbar {+ -GtkToolbar-button-relief: normal;++ padding: 8px;+ border-radius: 8px;+ border-style: none;+ background-image: linear-gradient(to bottom,+ mix(@theme_tooltip_bg_color, @subdued_color, 0.2),+ mix(@theme_tooltip_bg_color, @border_color, 0.2)+ );+ background-color: transparent;+ color: @theme_tooltip_fg_color;+}++.osd.toolbar .separator {+ color: @insensitive_border_color;+}++/* used by gnome-settings-daemon's media-keys OSD */+.osd.progressbar {+ background-color: @theme_selected_bg_color;+}++.osd.trough {+ background-color: mix(@button_top_active_color, @button_bottom_active_color, 0.5);+}++.osd GtkProgressBar,+GtkProgressBar.osd {+ -GtkProgressBar-xspacing: 0;+ -GtkProgressBar-yspacing: 4;+ -GtkProgressBar-min-horizontal-bar-height: 4;++ padding: 0;+}++.osd GtkProgressBar.progressbar,+GtkProgressBar.osd.progressbar {+ border-radius: 0;+ border-style: none;+ background-image: none;+ background-color: @theme_selected_bg_color;+}++.osd GtkProgressBar.trough,+GtkProgressBar.osd.trough {+ padding: 0;+ border-radius: 0;+ border-style: none;+ background-image: none;+ background-color: transparent;+}++.osd .view,+.osd.view {+ background-color: @theme_tooltip_bg_color;+ color: @theme_tooltip_fg_color;+}++/* used by Documents */+.osd .page-thumbnail {+ border-width: 1px;+ border-style: solid;+ border-color: @border_color;+ /* when there's no pixbuf yet */+ background-color: @theme_tooltip_bg_color;+}++/*************************+ * Touch text selections *+ *************************/+GtkBubbleWindow {+ border-radius: 8px;+}++GtkBubbleWindow.osd.background {+ background-color: @theme_tooltip_bg_color;+}++GtkBubbleWindow .toolbar {+ background-color: transparent;+}++/*******+ * CSD *+ *******/+.titlebar {+ background-image: linear-gradient(to bottom,+ @button_top_color,+ @theme_bg_color);+ border-radius: 7px 7px 0px 0px;+}++/* this is the default titlebar that is added by GTK+ * when client-side decorations are in use and the application+ * did not set a custom titlebar.+ */+.titlebar.default-decoration {+ border: none;+ box-shadow: none;+}++.titlebar .title {+ font: Bold 11;+}++.titlebar:backdrop {+ text-shadow: none;+ background-image: none;+ background-color: @theme_bg_color;+}++.titlebar .titlebutton {+ color: @theme_fg_color;+}++.titlebar .titlebutton:hover {+}++.titlebar .titlebutton:active {+}++.titlebar .titlebutton:backdrop {+ color: @internal_element_color;+}++.titlebar .titlebutton:backdrop:hover {+ color: @theme_fg_color;+}++.titlebar .right .titlebutton:first-child {+/* border-left: 1px solid @menu_separator; */+}++.titlebar .right .titlebutton:last-child {++}++.titlebar .left .titlebutton:last-child {+/* border-right: 1px solid @menu_separator; */+}++.titlebar .left .titlebutton:first-child {++}++.window-frame {+ border-radius: 7px 7px 0 0;+ border-width: 1px;+ border-style: solid;+ border-color: @border_color;+ box-shadow: 0 2px 8px 2px alpha(black, 0.5), 0 0 0 2px @border_color;++ /* this is used for the resize cursor area */+ margin: 10px;+}++.window-frame:backdrop {+ box-shadow: 0 2px 4px 0 alpha(black, 0.5), 0 0 0 2px @border_color;+}++/**********************+ * Fallback Mode Panel+ **********************/+.gnome-panel-menu-bar,+PanelApplet > GtkMenuBar.menubar,+PanelToplevel,+PanelWidget,+PanelAppletFrame,+PanelApplet {+ background-image: none;+ background-color: @os_chrome_bg_color;+ color: @os_chrome_fg_color;+}++ClockBox,+.gnome-panel-menu-bar.menubar,+PanelApplet > GtkMenuBar.menubar {+ font: bold;+}++.gnome-panel-menu-bar.menubar .menuitem:hover,+PanelApplet > GtkMenuBar.menubar .menuitem:hover {+ text-shadow: 0 1px @os_chrome_bg_color;+}++.gnome-panel-menu-bar.menubar .menu,+PanelApplet > GtkMenuBar.menubar .menu {+ font: regular;+}++.gnome-panel-menu-bar.menubar .menu:hover,+PanelApplet > GtkMenuBar.menubar .menu:hover {+ text-shadow: none;+}++.gnome-panel-menu-bar .menuitem:hover,+PanelApplet > GtkMenuBar.menubar .menuitem:hover {+ background-color: @os_chrome_selected_bg_color;+ color: @os_chrome_selected_fg_color;+}++PanelApplet .button,+PanelApplet .button:hover {+ padding: 4px;++ border-radius: 0;+ border-image: none;+ border-width: 0;++ background-image: none;+ background-color: @os_chrome_bg_color;++ color: @os_chrome_fg_color;+ text-shadow: none;+}++PanelApplet .button:active:hover,+PanelApplet .button:active {+ border-radius: 0;+ border-image: none;+ border-width: 0;+ background-image: none;+ background-color: @os_chrome_selected_bg_color;+}++PanelApplet:hover {+ color: @os_chrome_selected_fg_color;+}++PanelApplet:active,+PanelApplet:hover:active {+ color: @os_chrome_selected_fg_color;+ text-shadow: 0 1px @os_chrome_bg_color;+}++WnckPager {+ background-color: lighter(@os_chrome_selected_bg_color);+}++NaTrayApplet {+ -NaTrayApplet-icon-padding: 12;+ -NaTrayApplet-icon-size: 16;+}++GsmFailWhaleDialog {+ background-image: none;+ background-color: @os_chrome_bg_color;+ color: @os_chrome_fg_color;+}++GsmFailWhaleDialog .button,+GsmFailWhaleDialog .button:active {+ border-image: none;+ border-width: 1px;+ border-color: @alt_border_color;+}++GtkSourceView {+ background-color: @theme_bg_color;+ color: @theme_fg_color;+ font: monospace;+}+
+ app-data/themes/gtk/default/gtk.css view
@@ -0,0 +1,31 @@+/* Default color scheme */+@define-color theme_base_color #ffffff;+@define-color theme_text_color #2e3436;++@define-color border_color #888a85;+@define-color internal_element_color #888a85;++@define-color theme_selected_bg_color #4e9a06;+@define-color theme_selected_fg_color #36342e;++@define-color link_color #729fcf;+@define-color info_color #c4a000;+@define-color warning_color #f57900;+@define-color question_color #ad7fa8;+@define-color error_color #ef2929;+@define-color other_color #c17d11;++@define-color subdued_color shade(@theme_base_color, 0.7);+@define-color theme_bg_color mix(@theme_base_color, @subdued_color, 0.7);+@define-color theme_fg_color @theme_text_color;+@define-color theme_tooltip_bg_color mix(@subdued_color, #000000, 0.5);+@define-color theme_tooltip_fg_color @theme_text_color;++@define-color placeholder_text_color @internal_element_color;++@import url("gtk-common.css");+@import url("gtk-widgets-assets.css");+@import url("gtk-widgets-backgrounds-and-texts.css");+@import url("gtk-widgets-borders.css");+@import url("gtk-widgets.css");+@import url("gnome-applications.css");
+ app-data/themes/gtk/default/keybindings.css view
@@ -0,0 +1,10 @@++@binding-set treeViewExpander+{+ bind "Left" { "expand-collapse-cursor-row" (1, 0, 0) };+ bind "Right" { "expand-collapse-cursor-row" (1, 1, 0) };+}++GtkTreeView {+ gtk-key-bindings: treeViewExpander; +}
+ app-data/themes/gtk/default/reset.css view
@@ -0,0 +1,63 @@+/* from http://ruby-doc.org/gems/docs/g/gtk3-2.2.0/sample/gtk-demo/reset_css.html */++* {+ color: inherit;+ font-size: inherit;+ background-color: initial;+ font-family: inherit;+ font-style: inherit;+ font-variant: inherit;+ font-weight: inherit;+ text-shadow: inherit;+ icon-shadow: inherit;+ box-shadow: initial;+ margin-top: initial;+ margin-left: initial;+ margin-bottom: initial;+ margin-right: initial;+ padding-top: initial;+ padding-left: initial;+ padding-bottom: initial;+ padding-right: initial;+ border-top-style: initial;+ border-top-width: initial;+ border-left-style: initial;+ border-left-width: initial;+ border-bottom-style: initial;+ border-bottom-width: initial;+ border-right-style: initial;+ border-right-width: initial;+ border-top-left-radius: initial;+ border-top-right-radius: initial;+ border-bottom-right-radius: initial;+ border-bottom-left-radius: initial;+ outline-style: initial;+ outline-width: initial;+ outline-offset: initial;+ background-clip: initial;+ background-origin: initial;+ background-size: initial;+ background-position: initial;+ border-top-color: initial;+ border-right-color: initial;+ border-bottom-color: initial;+ border-left-color: initial;+ outline-color: initial;+ background-repeat: initial;+ background-image: initial;+ border-image-source: initial;+ border-image-repeat: initial;+ border-image-slice: initial;+ border-image-width: initial;+ transition-property: initial;+ transition-duration: initial;+ transition-timing-function: initial;+ transition-delay: initial;+ engine: initial;+ gtk-key-bindings: initial;++ -GtkWidget-focus-line-width: 0;+ -GtkWidget-focus-padding: 0;+ -GtkNotebook-initial-gap: 0;+}+
+ app-data/themes/gtksourceview/molokai.xml view
@@ -0,0 +1,33 @@+<?xml version="1.0" ?>+<style-scheme id="molokai" name="Molokai" version="1.0">+ <author/>+ <_description>+ Port of the Molokai Text Mate Theme to GTKSourceView. + </_description>+ <style foreground="#AE81FF" name="def:boolean"/>+ <style foreground="#AE81FF" name="def:number"/>+ <style foreground="#E6DB74" name="def:string"/>+ <style bold="true" foreground="#AE81FF" name="def:constant"/>+ <style background="#F8F8F0" foreground="#000000" name="cursor"/>+ <style background="#13354A" name="diff:added-line"/>+ <style background="#4C4745" foreground="#89807D" name="diff:changed-line"/>+ <style background="#1E0010" foreground="#960050" name="diff:removed-line"/>+ <style background="#1E0010" foreground="#960050" name="def:error"/>+ <style foreground="#A6E22E" name="def:function"/>+ <style foreground="#FD971F" name="def:identifier"/>+ <style bold="true" foreground="#F92672" name="def:keyword"/>+ <style background="#FD971F" bold="true" foreground="#000000" name="bracket-match"/>+ <style foreground="#A6E22E" name="def:preprocessor"/>+ <style background="#455354" foreground="#FFFFFF" name="search-match"/>+ <style background="#bg" foreground="#66D9EF" italic="true" name="def:specials"/>+ <style bold="true" foreground="#F92672" name="def:statement"/>+ <style foreground="#66D9EF" name="def:type"/>+ <style background="#272822" foreground="#F8F8F2" name="text"/>+ <style foreground="#75715E" name="def:comment"/>+ <style background="#3E3D32" name="current-line"/>+ <style background="#272822" foreground="#F8F8F2" name="text"/>+ <style foreground="#465457" name="def:comment"/>+ <style background="#3e3d32" name="current-line"/>+ <style background="#3b3a32" foreground="#bcbca7" name="line-numbers"/>+</style-scheme>+
+ app-data/ui.glade view
@@ -0,0 +1,122 @@+<?xml version="1.0" encoding="UTF-8"?>+<!-- Generated with glade 3.16.1 -->+<interface>+ <requires lib="gtk+" version="3.10"/>+ <object class="GtkWindow" id="mainWindow">+ <property name="can_focus">False</property>+ <child>+ <object class="GtkPaned" id="sidebarPaned">+ <property name="visible">True</property>+ <property name="can_focus">False</property>+ <child>+ <object class="GtkBox" id="box2">+ <property name="width_request">170</property>+ <property name="visible">True</property>+ <property name="can_focus">False</property>+ <property name="orientation">vertical</property>+ <child>+ <object class="GtkScrolledWindow" id="sidebarScroller">+ <property name="visible">True</property>+ <property name="can_focus">False</property>+ <child>+ <object class="GtkTreeView" id="directoryListing">+ <property name="visible">True</property>+ <property name="can_focus">True</property>+ <child internal-child="selection">+ <object class="GtkTreeSelection" id="treeview-selection1"/>+ </child>+ <style>+ <class name="sidebar"/>+ </style>+ </object>+ </child>+ </object>+ <packing>+ <property name="expand">True</property>+ <property name="fill">True</property>+ <property name="position">0</property>+ </packing>+ </child>+ <child>+ <object class="GtkEntry" id="directoryListingSearch">+ <property name="can_focus">True</property>+ <property name="hexpand">True</property>+ <property name="invisible_char">●</property>+ </object>+ <packing>+ <property name="expand">False</property>+ <property name="fill">True</property>+ <property name="position">1</property>+ </packing>+ </child>+ </object>+ <packing>+ <property name="resize">False</property>+ <property name="shrink">True</property>+ </packing>+ </child>+ <child>+ <object class="GtkBox" id="box1">+ <property name="visible">True</property>+ <property name="can_focus">False</property>+ <property name="orientation">vertical</property>+ <child>+ <object class="GtkNotebook" id="tabbedEditArea">+ <property name="visible">True</property>+ <property name="can_focus">True</property>+ <property name="hexpand">True</property>+ <property name="vexpand">True</property>+ <property name="show_border">False</property>+ </object>+ <packing>+ <property name="expand">True</property>+ <property name="fill">True</property>+ <property name="position">0</property>+ </packing>+ </child>+ <child>+ <object class="GtkBox" id="box6">+ <property name="visible">True</property>+ <property name="can_focus">False</property>+ <child>+ <object class="GtkEntry" id="command">+ <property name="visible">True</property>+ <property name="can_focus">True</property>+ <property name="invisible_char">●</property>+ <property name="caps_lock_warning">False</property>+ </object>+ <packing>+ <property name="expand">True</property>+ <property name="fill">True</property>+ <property name="position">0</property>+ </packing>+ </child>+ <child>+ <object class="GtkLabel" id="activeMode">+ <property name="visible">True</property>+ <property name="can_focus">False</property>+ </object>+ <packing>+ <property name="expand">False</property>+ <property name="fill">False</property>+ <property name="pack_type">end</property>+ <property name="position">1</property>+ </packing>+ </child>+ </object>+ <packing>+ <property name="expand">False</property>+ <property name="fill">False</property>+ <property name="position">2</property>+ </packing>+ </child>+ </object>+ <packing>+ <property name="resize">True</property>+ <property name="shrink">True</property>+ </packing>+ </child>+ </object>+ </child>+ </object>+</interface>
+ hob.cabal view
@@ -0,0 +1,71 @@+name: hob+version: 0.0.1.0+cabal-version: >=1.10+build-type: Simple+license: GPL-3+license-file: LICENSE+copyright: (c) Sarunas Valaskevicius+maintainer: Sarunas Valaskevicius <rakatan@gmail.com>+synopsis: A source code editor aiming for the convenience of use+description: A simple command based code editor being developed for the mouse-free workflow.+homepage: http://svalaskevicius.github.io/hob/+stability: alpha+bug-reports: http://github.com/svalaskevicius/hob/issues+category: IDE+author: Sarunas Valaskevicius+data-dir: app-data+data-files: ui.glade,+ themes/gtksourceview/*.xml,+ themes/gtk/default/*.css,+ themes/gtk/default/assets/*.png,+ themes/gtk/default/assets/*.svg++source-repository head+ type: git+ location: https://github.com/svalaskevicius/hob++executable hob+ build-depends: base >=4.2 && <5, gtk3 >=0.13.0.1, mtl >=2.1.0 && <2.2.0,+ directory -any, containers -any, filepath -any, hob, bytestring -any, text >= 1.1.1.0 && < 1.1.2.0,+ gtksourceview3 >=0.13.0.0+ main-is: hob.hs+ buildable: True+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs: src++library+ Exposed-modules: Hob.Ui, Hob.Ui.Editor, Hob.Ui.Sidebar, Hob.Ui.CommandEntry,+ Hob.Ui.SidebarSearch, Hob.Ui.Editor.Search,+ Hob.Command.FindText, Hob.Command.ReplaceText, Hob.Command.CloseCurrentTab,+ Hob.Command.SaveCurrentTab, Hob.Command.NewTab, Hob.Command.FocusCommandEntry,+ Hob.Command.FocusNextTab, Hob.Command.ReloadSidebarTree, Hob.Command.FocusSidebar,+ Hob.Command.FocusPreviousTab, Hob.Command.FocusNumberedTab,+ Hob.Context, Hob.Context.StyleContext, Hob.Context.FileContext, Hob.Context.UiContext,+ Hob.Context.Types, Hob.Context.Events, Hob.Context.CommandMatcher, Hob.Context.Editor,+ Hob.DirectoryTree, Hob.Control+ default-language: Haskell2010+ ghc-options:+ -Wall+ hs-source-dirs: src/lib+ build-depends: base >=4.7 && <5, containers -any,+ filepath -any, glib >=0.13.0.0, gtk3 >=0.13.0.1, pango >= 0.13.0.0,+ gtksourceview3 >=0.13.0.0, mtl >=2.1.0 && <2.2.0,+ transformers >=0.3.0.0 && <0.4, text >= 1.1.1.0,+ system-filepath -any, gtk-largeTreeStore >= 0.0.1.0, vector >= 0.10.12.2 && < 0.10.13++test-suite spec+ type:+ exitcode-stdio-1.0+ default-language: Haskell2010+ ghc-options:+ -Wall -Werror+ hs-source-dirs:+ test+ main-is:+ Spec.hs+ other-modules: Hob.Ui.SidebarSpec, Hob.Ui.EditorSpec, Hob.Ui.CommandEntrySpec, Hob.Ui.Editor.SearchSpec, Hob.Ui.SidebarSearchSpec, Hob.UiSpec, Hob.ContextSpec, Hob.ControlSpec, Hob.DirectoryTreeSpec, Hob.Command.FocusNextTabSpec, Hob.Command.FindTextSpec, Hob.Command.CloseCurrentTabSpec, Hob.Command.FocusSidebarSpec, Hob.Command.SaveCurrentTabSpec, Hob.Command.ReplaceTextSpec, Hob.Command.FocusCommandEntrySpec, Hob.Command.NewTabSpec, Hob.Command.FocusPreviousTabSpec, Hob.Command.FocusNumberedTabSpec, Hob.Command.ReloadSidebarTreeSpec, Hob.Context.FileContextSpec, Hob.Context.StyleContextSpec, HobTest.Sidebar, HobTest.Editor, HobTest.Context.Stubbed, HobTest.Context.Default, HobTest.Control+ build-depends:+ base >= 4.2 && <5, containers -any, mtl >=2.1.0 && <2.2.0,+ hspec >= 1.11, gtk3 >=0.13.0.1, hob, text >= 1.1.1.0, gtksourceview3 >=0.13.0.0
+ src/hob.hs view
@@ -0,0 +1,55 @@+module Main (main) where++import Control.Monad.Trans (liftIO)+import qualified Data.ByteString as BS+import qualified Data.Text.Encoding as E+import Graphics.UI.Gtk+import System.Directory+import System.Environment (getArgs)+import System.IO (hPutStr, stderr)++import Hob.Context+import Hob.Context.FileContext (FileLoader, FileTreeLoader, FileWriter,+ defaultFileContext)+import Hob.Context.StyleContext (defaultStyleContext)+import Hob.Context.UiContext+import Hob.DirectoryTree+import Hob.Ui++import Paths_hob++main :: IO ()+main = do+ fileCtx <- getFileContext+ styleCtx <- getStyleContext+ ctx <- loadGui fileCtx styleCtx+ let window = mainWindow . uiContext $ ctx+ _ <- window `on` deleteEvent $ liftIO mainQuit >> return False+ widgetShow window+ mainGUI+ where+ getFileContext = do+ projectRoot <- getProjectDirectory+ defaultFileContext loadFile storeFile (fileTreeFromDirectory projectRoot)+ getStyleContext = defaultStyleContext =<< getDataDir+ getProjectDirectory = do+ args <- getArgs+ case args of+ [] -> getCurrentDirectory+ [path] -> canonicalizePath path+ _ -> error "unsupported command options"+++fileTreeFromDirectory :: FilePath -> FileTreeLoader+fileTreeFromDirectory = fileTreeGenerator getDirectoryContents doesDirectoryExist++loadFile :: FileLoader+loadFile path = do+ contents <- BS.readFile path+ checkError $ E.decodeUtf8' contents+ where checkError (Left e) = do hPutStr stderr (show e)+ return Nothing+ checkError (Right t) = return $ Just t++storeFile :: FileWriter+storeFile path = BS.writeFile path . E.encodeUtf8
+ src/lib/Hob/Command/CloseCurrentTab.hs view
@@ -0,0 +1,24 @@+module Hob.Command.CloseCurrentTab (closeCurrentEditorTab) where+++import Control.Monad.Trans (liftIO)+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.UiContext++closeCurrentEditorTab :: CommandHandler+closeCurrentEditorTab = CommandHandler Nothing closeCurrentEditorTabHandler++closeCurrentEditorTabHandler :: App()+closeCurrentEditorTabHandler = do+ ui <- fromContext uiContext+ let tabbed = mainNotebook ui+ currentPage <- liftIO $ notebookGetCurrentPage tabbed+ nthPage <- liftIO $ notebookGetNthPage tabbed currentPage+ case nthPage of+ Just pageContents -> do+ liftIO $ notebookRemovePage tabbed currentPage+ liftIO $ widgetDestroy pageContents+ Nothing -> return ()+
+ src/lib/Hob/Command/FindText.hs view
@@ -0,0 +1,54 @@+module Hob.Command.FindText (+ searchCommandHandler,+ searchNextCommandHandler,+ searchBackwardsCommandHandler,+ searchPreview,+ searchResetPreview,+ searchMode,+ ) where++import Data.Monoid (mconcat)+import Graphics.UI.Gtk++import Hob.Context+import Hob.Ui.Editor+import Hob.Ui.Editor.Search++searchCommandHandler :: String -> CommandHandler+searchCommandHandler searchText = CommandHandler (Just $ PreviewCommandHandler (searchPreview searchText) searchResetPreview) (searchStart searchText)++searchNextCommandHandler :: CommandHandler+searchNextCommandHandler = CommandHandler Nothing searchNext++searchBackwardsCommandHandler :: CommandHandler+searchBackwardsCommandHandler = CommandHandler Nothing searchPrevious++searchPreview :: String -> App()+searchPreview text = invokeOnActiveEditor (`highlightSearchPreview` text)++searchReset :: App()+searchReset = invokeOnActiveEditor resetSearch++searchResetPreview :: App()+searchResetPreview = invokeOnActiveEditor resetSearchPreview++searchNext :: App()+searchNext = invokeOnActiveEditor findNext++searchPrevious :: App()+searchPrevious = invokeOnActiveEditor findPrevious++searchStart :: String -> App()+searchStart text = do+ enterMode searchMode+ invokeOnActiveEditor $ \editor -> do+ findFirstFromCursor editor text+ widgetGrabFocus editor++searchMode :: Mode+searchMode = Mode "search" matcher searchReset+ where matcher = mconcat [+ createMatcherForKeyBinding ([Control], "Down") searchNextCommandHandler,+ createMatcherForKeyBinding ([Control], "Up") searchBackwardsCommandHandler]++
+ src/lib/Hob/Command/FocusCommandEntry.hs view
@@ -0,0 +1,47 @@+module Hob.Command.FocusCommandEntry (+ toggleFocusOnCommandEntryCommandHandler,+ focusActiveEditorAndExitLastModeCommandHandler,+ focusCommandEntryCommandHandler,+ ) where++import Control.Monad.Reader+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.UiContext+import Hob.Control+import Hob.Ui.Editor++focusCommandEntryCommandHandler :: CommandHandler+focusCommandEntryCommandHandler = CommandHandler Nothing focusCommandEntry++focusActiveEditorAndExitLastModeCommandHandler :: CommandHandler+focusActiveEditorAndExitLastModeCommandHandler = CommandHandler Nothing focusActiveEditorAndExitLastMode++toggleFocusOnCommandEntryCommandHandler :: CommandHandler+toggleFocusOnCommandEntryCommandHandler = CommandHandler Nothing toggleFocusOnCommandEntry+++focusCommandEntry :: App()+focusCommandEntry = do+ ctx <- ask+ liftIO $ widgetGrabFocus $ cmdEntry ctx+ where cmdEntry ctx = commandEntry.uiContext $ ctx++focusActiveEditorAndExitLastMode :: App()+focusActiveEditorAndExitLastMode = do+ exitLastMode+ ctx <- ask+ editor <- liftIO $ getActiveEditor ctx+ liftIO $ maybeDo widgetGrabFocus editor++toggleFocusOnCommandEntry :: App()+toggleFocusOnCommandEntry = do+ ctx <- ask+ isFocused <- liftIO $ widgetGetIsFocus $ cmdEntry ctx+ if isFocused then do+ editor <- liftIO $ getActiveEditor ctx+ liftIO $ maybeDo widgetGrabFocus editor+ else+ liftIO $ widgetGrabFocus $ cmdEntry ctx+ where cmdEntry ctx = commandEntry.uiContext $ ctx
+ src/lib/Hob/Command/FocusNextTab.hs view
@@ -0,0 +1,22 @@+module Hob.Command.FocusNextTab (focusNextTabCommandHandler) where++import Control.Monad.Trans (liftIO)+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.UiContext++focusNextTabCommandHandler :: CommandHandler+focusNextTabCommandHandler = CommandHandler Nothing focusNextTab++focusNextTab :: App()+focusNextTab = do+ ui <- fromContext uiContext+ let notebook = mainNotebook ui+ pages <- liftIO $ notebookGetNPages notebook+ currentPage <- liftIO $ notebookGetCurrentPage notebook+ liftIO $ notebookSetCurrentPage notebook (nextPage currentPage pages)+ where+ nextPage currentPage pages =+ if currentPage == (pages - 1) then 0 else currentPage + 1+
+ src/lib/Hob/Command/FocusNumberedTab.hs view
@@ -0,0 +1,18 @@+module Hob.Command.FocusNumberedTab (focusNumberedTabCommandHandler) where++import Control.Monad (when)+import Control.Monad.Trans (liftIO)+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.UiContext++focusNumberedTabCommandHandler :: Int -> CommandHandler+focusNumberedTabCommandHandler nr = CommandHandler Nothing $ focusNumberedTab nr++focusNumberedTab :: Int -> App()+focusNumberedTab nr = do+ ui <- fromContext uiContext+ let notebook = mainNotebook ui+ pages <- liftIO $ notebookGetNPages notebook+ when (nr >= 0 && nr < pages) $ liftIO $ notebookSetCurrentPage notebook nr
+ src/lib/Hob/Command/FocusPreviousTab.hs view
@@ -0,0 +1,22 @@+module Hob.Command.FocusPreviousTab (focusPreviousTabCommandHandler) where++import Control.Monad.Trans (liftIO)+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.UiContext++focusPreviousTabCommandHandler :: CommandHandler+focusPreviousTabCommandHandler = CommandHandler Nothing focusPreviousTab++focusPreviousTab :: App()+focusPreviousTab = do+ ui <- fromContext uiContext+ let notebook = mainNotebook ui+ pages <- liftIO $ notebookGetNPages notebook+ currentPage <- liftIO $ notebookGetCurrentPage notebook+ liftIO $ notebookSetCurrentPage notebook (previousPage currentPage pages)+ where+ previousPage currentPage pages =+ if currentPage == 0 then pages - 1 else currentPage - 1+
+ src/lib/Hob/Command/FocusSidebar.hs view
@@ -0,0 +1,37 @@+module Hob.Command.FocusSidebar (+ focusSidebarCommandHandler,+ syncFocusSidebarCommandHandler+ ) where++import Control.Monad.Reader+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.UiContext+import Hob.Control+import Hob.Ui.Editor (getActiveEditor, getEditorFilePath)+import Hob.Ui.Sidebar (syncPathToSidebar)++focusSidebarCommandHandler :: CommandHandler+focusSidebarCommandHandler = CommandHandler Nothing focusSidebar++syncFocusSidebarCommandHandler :: CommandHandler+syncFocusSidebarCommandHandler = CommandHandler Nothing syncFocusSidebar++focusSidebar :: App()+focusSidebar = do+ ctx <- ask+ liftIO $ widgetGrabFocus . sidebarTree . uiContext $ ctx++syncActiveEditorPathToSidebar :: App()+syncActiveEditorPathToSidebar = do+ ctx <- ask+ editor <- liftIO $ getActiveEditor ctx+ maybeDo syncToEditor editor+ where syncToEditor editor = maybeDo syncPathToSidebar =<< liftIO (getEditorFilePath editor)+++syncFocusSidebar :: App()+syncFocusSidebar = syncActiveEditorPathToSidebar >> focusSidebar++
+ src/lib/Hob/Command/NewTab.hs view
@@ -0,0 +1,51 @@+module Hob.Command.NewTab (+ launchNewFileEditor,+ editNewFile,+ editNewFileCommandHandler,+ NewFileEditorLauncher) where+++import Control.Monad.Reader+import Data.Maybe (mapMaybe)+import Data.Text (pack)+import Graphics.UI.Gtk++import Hob.Context+import Hob.Context.FileContext+import Hob.Context.UiContext+import Hob.Control+import Hob.Ui.Editor++type NewFileEditorLauncher = FilePath -> IO ()++editNewFileCommandHandler :: CommandHandler+editNewFileCommandHandler = CommandHandler Nothing editNewFile++launchNewFileEditor :: Context -> Notebook -> NewFileEditorLauncher+launchNewFileEditor ctx targetNotebook filePath = do+ let fileLoader = contextFileLoader . fileContext $ ctx+ currentEditors <- mapM getEditorFromNotebookTab <=< containerGetChildren $ targetNotebook+ editorsForFile <- filterM (\(_, ed) -> isEditorFileMatching ed ) $ numberedJusts currentEditors+ case alreadyLoadedPage editorsForFile of+ Just nr -> notebookSetCurrentPage targetNotebook nr+ Nothing -> maybeDo launchEditor =<< fileLoader filePath++ where launchEditor text = deferredRunner ctx $ newEditorForText targetNotebook (Just filePath) text+ isEditorFileMatching editor = do+ f <- getEditorFilePath editor+ return $ maybe False (filePath ==) f+ alreadyLoadedPage [(nr, _)] = Just nr+ alreadyLoadedPage _ = Nothing++editNewFile :: App()+editNewFile = do+ ctx <- ask+ let tabbed = mainNotebook.uiContext $ ctx+ newEditorForText tabbed Nothing $ pack ""++liftTupledMaybe :: (a, Maybe b) -> Maybe (a, b)+liftTupledMaybe (x, Just y) = Just (x, y)+liftTupledMaybe (_, Nothing) = Nothing++numberedJusts :: [Maybe a] -> [(Int, a)]+numberedJusts a = mapMaybe liftTupledMaybe $ zip [0..] a
+ src/lib/Hob/Command/ReloadSidebarTree.hs view
@@ -0,0 +1,11 @@+module Hob.Command.ReloadSidebarTree (reloadSidebarTreeCommandHandler) where++import Hob.Context+import Hob.Ui.Sidebar++reloadSidebarTreeCommandHandler :: CommandHandler+reloadSidebarTreeCommandHandler = CommandHandler Nothing reloadCmd++reloadCmd :: App()+reloadCmd = reloadSidebarTree+
+ src/lib/Hob/Command/ReplaceText.hs view
@@ -0,0 +1,67 @@+module Hob.Command.ReplaceText (+ createMatcherForReplace,+ replaceCommandHandler,+ replaceNextCommandHandler,+ ) where++import Data.Monoid (mconcat)+import Graphics.UI.Gtk++import Hob.Command.FindText+import Hob.Context+import Hob.Ui.Editor+import Hob.Ui.Editor.Search++createMatcherForReplace :: Char -> (String -> String -> CommandHandler) -> CommandMatcher+createMatcherForReplace prefix handler = CommandMatcher (const Nothing) match+ where match [] = Nothing+ match (p:ps)+ | p == prefix = matchSearchAndReplaceFromStart ps+ | otherwise = Nothing++ matchSearchAndReplaceFromStart [] = Nothing+ matchSearchAndReplaceFromStart (separator:xs) = matchSearchAndReplaceFromSearch separator xs ""++ matchSearchAndReplaceFromSearch _ [] _ = Nothing+ matchSearchAndReplaceFromSearch separator (x:xs) accumSearch+ | '\\' == x = case xs of+ [] -> Nothing+ (s:xss) -> if s == separator then matchSearchAndReplaceFromSearch separator xss (accumSearch++[separator])+ else matchSearchAndReplaceFromSearch separator xs (accumSearch++[x])+ | separator == x = matchSearchAndReplaceFromReplace separator xs accumSearch ""+ | otherwise = matchSearchAndReplaceFromSearch separator xs (accumSearch++[x])++ matchSearchAndReplaceFromReplace _ [] search accumReplace = Just $ handler search accumReplace+ matchSearchAndReplaceFromReplace separator (x:xs) search accumReplace+ | '\\' == x = case xs of+ [] -> Just $ handler search (accumReplace++[x])+ (s:xss) -> if s == separator then matchSearchAndReplaceFromReplace separator xss search (accumReplace++[separator])+ else matchSearchAndReplaceFromReplace separator xs search (accumReplace++[x])+ | separator == x = Just $ handler search accumReplace+ | otherwise = matchSearchAndReplaceFromReplace separator xs search (accumReplace++[x])++replaceCommandHandler :: String -> String -> CommandHandler+replaceCommandHandler searchText replaceText = CommandHandler (Just $ PreviewCommandHandler (searchPreview searchText) searchResetPreview) (replaceStart searchText replaceText)++replaceNextCommandHandler :: CommandHandler+replaceNextCommandHandler = CommandHandler Nothing invokeReplaceNext++replaceStart :: String -> String -> App()+replaceStart searchText replaceText = do+ enterMode replaceMode+ invokeOnActiveEditor $ \editor -> do+ startReplace editor searchText replaceText+ widgetGrabFocus editor++invokeReplaceNext :: App()+invokeReplaceNext = invokeOnActiveEditor replaceNext++replaceReset :: App()+replaceReset = invokeOnActiveEditor resetReplace++replaceMode :: Mode+replaceMode = Mode "replace" matcher replaceReset+ where matcher = mconcat [ commandMatcher searchMode+ , createMatcherForKeyBinding ([Shift, Control], "Down") replaceNextCommandHandler+ ]+
+ src/lib/Hob/Command/SaveCurrentTab.hs view
@@ -0,0 +1,59 @@+module Hob.Command.SaveCurrentTab (+ NewFileNameChooser,+ saveCurrentEditorTab,+ saveCurrentEditorTabHandler) where++import Control.Monad.Reader+import Graphics.UI.Gtk+import Graphics.UI.Gtk.SourceView (SourceView)++import Hob.Context+import Hob.Context.FileContext+import Hob.Context.UiContext+import Hob.Control+import Hob.Ui.Editor++type NewFileNameChooser = IO (Maybe FilePath)++saveCurrentEditorTab :: CommandHandler+saveCurrentEditorTab = CommandHandler Nothing (do+ ctx <- ask+ saveCurrentEditorTabHandler $ fileChooser ctx)+ where+ fileChooser :: Context -> IO (Maybe FilePath)+ fileChooser ctx = do+ dialog <- fileChooserDialogNew Nothing (Just $ mainWindow.uiContext $ ctx) FileChooserActionSave [("Cancel", ResponseCancel), ("Save", ResponseOk)]+ resp <- dialogRun dialog+ file <- if resp == ResponseOk then fileChooserGetFilename dialog else return Nothing+ widgetDestroy dialog+ return file++saveCurrentEditorTabHandler :: NewFileNameChooser -> App()+saveCurrentEditorTabHandler newFileNameChooser = do+ ctx <- ask+ maybeEditor <- liftIO $ getActiveEditor ctx+ maybeDo (saveInContext newFileNameChooser) maybeEditor+++saveInContext :: NewFileNameChooser -> SourceView -> App ()+saveInContext newFileNameChooser editor = do+ ctx <- ask+ liftIO $ saveEditor ctx+ where fileWriter ctx = contextFileWriter . fileContext $ ctx+ saveEditor ctx = do+ path <- getEditorFilePath editor+ case path of+ Just filePath -> saveEditorContents ctx filePath+ Nothing -> askForFile $ saveAsNewFile ctx+ askForFile onSuccess = newFileNameChooser >>= maybe (return()) onSuccess+ saveAsNewFile ctx filePath = do+ saveEditorContents ctx filePath+ setEditorFilePath editor $ Just filePath+ updateEditorTitle editor++ saveEditorContents ctx filePath = do+ textBuf <- textViewGetBuffer editor+ text <- get textBuf textBufferText+ fileWriter ctx filePath text+ textBuf `set` [textBufferModified := False]+ return ()
+ src/lib/Hob/Context.hs view
@@ -0,0 +1,85 @@+module Hob.Context (+ App,+ Context(..),+ PreviewCommandHandler(..),+ CommandHandler(..),+ CommandMatcher(..),+ KeyboardBinding,+ KeyCommandMatcher,+ TextCommandMatcher,+ Mode(..),+ Event(..),+ Editor(..),+ EditorList(..),+ initContext,+ runOnEditor,+ enterMode,+ exitLastMode,+ activeModes,+ deferredRunner,+ registerEventHandler,+ emitEvent,+ createMatcherForPrefix,+ createMatcherForCommand,+ createMatcherForKeyBinding,+ fromContext,+ runApp,+ getActiveCommands,+) where++import Control.Concurrent.MVar+import Control.Monad.Reader+import Graphics.UI.Gtk (postGUIAsync)+import GtkExtras.LargeTreeStore as LTS (TreeStore)++import Hob.Context.CommandMatcher+import Hob.Context.Editor+import Hob.Context.Events+import Hob.Context.FileContext+import Hob.Context.StyleContext+import Hob.Context.Types+import Hob.Context.UiContext+import Hob.DirectoryTree++++initContext :: StyleContext -> FileContext -> UiContext -> LTS.TreeStore DirectoryTreeElement -> CommandMatcher -> IO Context+initContext styleCtx fileCtx uiCtx treeModel initCommands = do+ actionSync <- newMVar True+ deferredMessagesRef <- newMVar []+ bus <- initEventBus+ editorList <- initEditors+ initialisedIdGenerator <- initIdGenerator+ let ctx = Context styleCtx fileCtx uiCtx treeModel initCommands editorList (messageRunner actionSync deferredMessagesRef) bus initialisedIdGenerator+ return ctx+ where+ messageRunner actionSync deferredMessagesRef ctx message = do+ queueMessage deferredMessagesRef message+ sync <- tryTakeMVar actionSync+ case sync of+ Just _ -> flushMessageQueue deferredMessagesRef ctx >> putMVar actionSync True+ Nothing -> return()+ flushMessageQueue deferredMessagesRef ctx = do+ messages <- swapMVar deferredMessagesRef []+ unless (null messages) $ foldM runMessage ctx messages >>= flushMessageQueue deferredMessagesRef+ queueMessage deferredMessagesRef message = modifyMVar_ deferredMessagesRef (\messages -> return $ messages ++ [message])++runApp :: Context -> App a -> IO a+runApp ctx appSteps = runReaderT appSteps ctx++runMessage :: Context -> Message -> IO Context+runMessage ctx (AppAction action) = runApp ctx action >> return ctx++deferredRunner :: Context -> App() -> IO()+deferredRunner ctx actions = postGUIAsync $ messageLoop ctx ctx $ AppAction actions++initIdGenerator :: IO (IO Int)+initIdGenerator = do+ generatorStorage <- newMVar 0+ return $ do+ lastGeneratdId <- takeMVar generatorStorage+ let newId = lastGeneratdId + 1+ putMVar generatorStorage newId+ return newId++
+ src/lib/Hob/Context/CommandMatcher.hs view
@@ -0,0 +1,33 @@+module Hob.Context.CommandMatcher (+ createMatcherForPrefix,+ createMatcherForCommand,+ createMatcherForKeyBinding,+) where++import Hob.Context.Types+++createMatcherForPrefix :: String -> (String -> CommandHandler) -> CommandMatcher+createMatcherForPrefix prefix handler = CommandMatcher (const Nothing) (matchHandler prefix)+ where+ matchHandler :: String -> String -> Maybe CommandHandler+ matchHandler (p:xs) (t:xt) = if p == t then matchHandler xs xt else Nothing+ matchHandler "" params = Just $ handler params+ matchHandler _ "" = Nothing++createMatcherForCommand :: String -> CommandHandler -> CommandMatcher+createMatcherForCommand command handler = CommandMatcher (const Nothing) (matchHandler command)+ where+ matchHandler :: String -> String -> Maybe CommandHandler+ matchHandler (p:xs) (t:xt) = if p == t then matchHandler xs xt else Nothing+ matchHandler "" "" = Just handler+ matchHandler _ "" = Nothing+ matchHandler "" _ = Nothing++createMatcherForKeyBinding :: KeyboardBinding -> CommandHandler -> CommandMatcher+createMatcherForKeyBinding keyBinding handler = CommandMatcher (matchHandler keyBinding) (const Nothing)+ where+ matchHandler :: KeyboardBinding -> KeyboardBinding -> Maybe CommandHandler+ matchHandler boundKey matchedKey = if boundKey == matchedKey then Just handler else Nothing++
+ src/lib/Hob/Context/Editor.hs view
@@ -0,0 +1,90 @@+module Hob.Context.Editor (+ initEditors,+ runOnEditor,+ enterMode,+ exitLastMode,+ activeModes,+ getActiveCommands,+ ) where++import Control.Concurrent.MVar+import Control.Monad.Reader+import Data.Monoid++import Hob.Context.Events+import Hob.Context.Types+++runOnEditor :: (Editor -> Editor -> a) -> Editor -> a+runOnEditor f editor = f editor editor++initEditors :: IO EditorList+initEditors = do+ editorList <- newMVar []+ return $ EditorList (updateEditorsHandler editorList) (getEditorsHandler editorList)+ where+ updateEditorsHandler editorList updater = do+ oldEditors <- takeMVar editorList+ newEditors <- updater oldEditors+ putMVar editorList newEditors+ getEditorsHandler = readMVar++currentEditor :: App (Maybe Editor)+currentEditor = do+ editorList <- fromContext editors+ active <- filterM (\e -> isCurrentlyActive e e) =<< liftIO (getEditors editorList)+ return $+ if null active then Nothing+ else Just $ head active++enterMode :: Mode -> App()+enterMode mode = do+ updateActiveEditor $ \editor -> do+ editor' <- clearEditorModes editor+ runOnEditor enterEditorMode editor' mode+ emitEvent $ Event "core.mode.change"+ where clearEditorModes editor = do+ modes <- runOnEditor modeStack editor+ if not . null $ modes then do+ editor' <- runOnEditor exitLastEditorMode editor+ clearEditorModes editor'+ else return editor++activeModes :: App (Maybe [Mode])+activeModes = do+ active <- currentEditor+ maybe (return Nothing) (runOnEditor modeStack >=> return . Just) active++exitLastMode :: App()+exitLastMode = do+ updateActiveEditor $ \editor -> runOnEditor exitLastEditorMode editor+ emitEvent $ Event "core.mode.change"++updateActiveEditor :: (Editor -> App Editor) -> App()+updateActiveEditor actions = do+ ctx <- ask+ editorList <- fromContext editors+ liftIO $ updateEditors editorList $ \oldEditors -> runReaderT (updateActiveEditorHandler oldEditors) ctx+ where+ updateActiveEditorHandler oldEditors = do+ (e1, e2) <- splitBeforeFirstActive oldEditors+ if null e2 then return oldEditors+ else do+ let active = head e2+ active' <- actions active+ return $ e1 ++ [active'] ++ tail e2+ splitBeforeFirstActive [] = return ([], [])+ splitBeforeFirstActive (x:xs) = do+ active <- runOnEditor isCurrentlyActive x+ if active then return ([], x:xs)+ else do+ (n, ns) <- splitBeforeFirstActive xs+ return (x:n, ns)++getActiveCommands :: App CommandMatcher+getActiveCommands = do+ base <- asks baseCommands+ maybeModes <- activeModes+ maybe (return base)+ (\modes -> return $ base `mappend` mconcat (fmap commandMatcher modes))+ maybeModes
+ src/lib/Hob/Context/Events.hs view
@@ -0,0 +1,45 @@+module Hob.Context.Events (+ initEventBus,+ registerEventHandler,+ emitEvent,+) where++import Control.Concurrent.MVar+import Control.Monad.Reader++import Hob.Context.Types++initEventBus :: IO EventBus+initEventBus = do+ bus <- newMVar []+ return $ EventBus (addEventListener bus) (lookupEvent bus)+ where+ addEventListener bus event action = do+ listeners <- takeMVar bus+ putMVar bus $ combineEventListeners event action listeners++ combineEventListeners :: Event -> App() -> [(Event, [App()])] -> [(Event, [App()])]+ combineEventListeners event action [] = [(event, [action])]+ combineEventListeners event action (x@(evt, initHandlers):xs) =+ if evt == event then (evt, action:initHandlers) : xs+ else x : combineEventListeners event action xs++ lookupEvent bus event = do+ listeners <- readMVar bus+ return $ findEvent event listeners++ findEvent _ [] = []+ findEvent event ((evt, handlers):xs) = if evt == event then handlers+ else findEvent event xs++registerEventHandler :: Event -> App() -> App()+registerEventHandler event handler = do+ bus <- fromContext eventBus+ liftIO $ addListener bus event handler++emitEvent :: Event -> App()+emitEvent event = do+ bus <- fromContext eventBus+ handlers <- liftIO $ listenersForEvent bus event+ sequence_ handlers+
+ src/lib/Hob/Context/FileContext.hs view
@@ -0,0 +1,35 @@+module Hob.Context.FileContext (+ FileContext(..),+ FileLoader,+ FileWriter,+ FileTreeLoader,+ defaultFileContext,+ sourceLanguage+) where++import Data.Text (Text)+import Data.Tree (Forest)+import Graphics.UI.Gtk.SourceView (SourceLanguage, SourceLanguageManager,+ sourceLanguageManagerGuessLanguage,+ sourceLanguageManagerNew)++import Hob.DirectoryTree++type FileLoader = FilePath -> IO (Maybe Text)+type FileWriter = FilePath -> Text -> IO ()+type FileTreeLoader = IO (Forest DirectoryTreeElement)++data FileContext = FileContext {+ contextLanguageManager :: SourceLanguageManager,+ contextFileLoader :: FileLoader,+ contextFileWriter :: FileWriter,+ contextFileTreeLoader :: FileTreeLoader+}++defaultFileContext :: FileLoader -> FileWriter -> FileTreeLoader -> IO FileContext+defaultFileContext loader writer treeLoader = do+ languageManager <- sourceLanguageManagerNew+ return $ FileContext languageManager loader writer treeLoader++sourceLanguage :: FileContext -> FilePath -> IO (Maybe SourceLanguage)+sourceLanguage ctx filePath = sourceLanguageManagerGuessLanguage (contextLanguageManager ctx) (Just filePath) (Nothing::Maybe String)
+ src/lib/Hob/Context/StyleContext.hs view
@@ -0,0 +1,43 @@+module Hob.Context.StyleContext (+ StyleContext,+ defaultStyleContext,+ uiFile,+ uiTheme,+ sourceStyleScheme,+ sourceStyleFont+) where++import Control.Monad (liftM)+import Graphics.Rendering.Pango.Font (FontDescription,+ fontDescriptionFromString)+import Graphics.UI.Gtk.SourceView (SourceStyleScheme,+ SourceStyleSchemeManager,+ sourceStyleSchemeManagerGetDefault,+ sourceStyleSchemeManagerGetScheme,+ sourceStyleSchemeManagerSetSearchPath)+import System.FilePath ((</>))++data StyleContext = StyleContext {+ contextDataPath :: FilePath,+ contextStyleManager :: SourceStyleSchemeManager+}++defaultStyleContext :: FilePath -> IO StyleContext+defaultStyleContext dataDir = do+ styleManager <- sourceStyleSchemeManagerGetDefault+ sourceStyleSchemeManagerSetSearchPath styleManager (Just [dataDir </> "themes" </> "gtksourceview"])+ return $ StyleContext dataDir styleManager++uiFile :: StyleContext -> FilePath+uiFile ctx = contextDataPath ctx </> "ui.glade"++uiTheme :: StyleContext -> FilePath+uiTheme ctx = contextDataPath ctx </> "themes" </> "gtk" </> "default" </> "gtk-dark.css"++sourceStyleScheme :: StyleContext -> Maybe FilePath -> IO (Maybe SourceStyleScheme)+sourceStyleScheme ctx _ = do+ style <- sourceStyleSchemeManagerGetScheme (contextStyleManager ctx) "molokai"+ return $ Just style++sourceStyleFont :: StyleContext -> Maybe FilePath -> IO (Maybe FontDescription)+sourceStyleFont _ _ = liftM Just $ fontDescriptionFromString "monospace 12"
+ src/lib/Hob/Context/Types.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE MultiParamTypeClasses #-}++module Hob.Context.Types (+ App,+ EventBus(..),+ Context(..),+ PreviewCommandHandler(..),+ CommandHandler(..),+ CommandMatcher(..),+ Message(..),+ KeyboardBinding,+ KeyCommandMatcher,+ TextCommandMatcher,+ Mode(..),+ Event(..),+ Editor(..),+ EditorList(..),+ fromContext,+ ) where++import Control.Monad.Reader+import Data.Maybe (isJust)+import Data.Monoid+import Graphics.UI.Gtk (Modifier)+import GtkExtras.LargeTreeStore as LTS (TreeStore)++import Hob.Context.FileContext+import Hob.Context.StyleContext+import Hob.Context.UiContext+import Hob.DirectoryTree+++type App = ReaderT Context IO++newtype Event = Event String deriving (Eq, Show)++data Editor = Editor {+ editorId :: Editor -> App Int,+ enterEditorMode :: Editor -> Mode -> App Editor,+ exitLastEditorMode :: Editor -> App Editor,+ modeStack :: Editor -> App [Mode],+ isCurrentlyActive :: Editor -> App Bool+}++data EventBus = EventBus {+ addListener :: Event -> App() -> IO(),+ listenersForEvent :: Event -> IO [App()]+}++data EditorList = EditorList {+ updateEditors :: ([Editor] -> IO [Editor]) -> IO(),+ getEditors :: IO [Editor]+}++data Context = Context {+ styleContext :: StyleContext,+ fileContext :: FileContext,+ uiContext :: UiContext,+ fileTreeStore :: LTS.TreeStore DirectoryTreeElement,+ baseCommands :: CommandMatcher,+ editors :: EditorList,+ messageLoop :: Context -> Message -> IO(),+ eventBus :: EventBus,+ idGenerator :: IO Int+}++data Mode = Mode {+ modeName :: String,+ commandMatcher :: CommandMatcher,+ cleanup :: App()+}++data Message = AppAction (App())+++data PreviewCommandHandler = PreviewCommandHandler {+ previewExecute :: App(),+ previewReset :: App()+ }++data CommandHandler = CommandHandler {+ commandPreview :: Maybe PreviewCommandHandler,+ commandExecute :: App()+ }++type KeyboardBinding = ([Modifier], String)+type SingleCommandMatcher a = a -> Maybe CommandHandler+type KeyCommandMatcher = SingleCommandMatcher KeyboardBinding+type TextCommandMatcher = SingleCommandMatcher String++data CommandMatcher = CommandMatcher {+ matchKeyBinding :: KeyCommandMatcher,+ matchCommand :: TextCommandMatcher+ }++instance Monoid CommandMatcher where+ mempty = CommandMatcher (const Nothing) (const Nothing)+ mappend l r = CommandMatcher (combineMatchKeyBinding l r) (combineMatchCommand l r)+ where combineMatchKeyBinding = combineMatcher matchKeyBinding+ combineMatchCommand = combineMatcher matchCommand+++fromContext :: MonadReader r m => (r -> a) -> m a+fromContext = asks+++combineMatcher :: (CommandMatcher -> SingleCommandMatcher a) -> CommandMatcher -> CommandMatcher -> SingleCommandMatcher a+combineMatcher combiner l r cmd = if isJust rightResult then rightResult else leftResult+ where leftResult = combiner l cmd+ rightResult = combiner r cmd
+ src/lib/Hob/Context/UiContext.hs view
@@ -0,0 +1,14 @@+module Hob.Context.UiContext (+ UiContext(..)+) where++import Graphics.UI.Gtk (Entry, Label, Notebook, TreeView, Window)++data UiContext = UiContext {+ mainWindow :: Window,+ mainNotebook :: Notebook,+ commandEntry :: Entry,+ sidebarTree :: TreeView,+ sidebarTreeSearch :: Entry,+ activeModesLabel :: Label+}
+ src/lib/Hob/Control.hs view
@@ -0,0 +1,15 @@+module Hob.Control (+ maybeDo,+ flushEvents+) where++import Control.Monad (when)+import Graphics.UI.Gtk (eventsPending, mainIteration)++maybeDo :: Monad b => (a -> b ()) -> Maybe a -> b ()+maybeDo = maybe (return())++flushEvents :: IO()+flushEvents = do+ pending <- eventsPending+ when (pending > 0) $ mainIteration >> flushEvents
+ src/lib/Hob/DirectoryTree.hs view
@@ -0,0 +1,54 @@+module Hob.DirectoryTree (+ DirectoryForest,+ DirectoryTreeLoader,+ DirectoryReader,+ IsDirectoryCheck,+ DirectoryTreeElement(..),+ fileTreeGenerator+) where++import Control.Monad (forM)+import Data.List (sortBy)+import Data.Tree+import System.FilePath++type IsDirectory = Bool++data DirectoryTreeElement = DirectoryTreeElement { elementLabel :: String, elementPath :: FilePath, isDirectory :: IsDirectory }++instance Show (DirectoryTreeElement) where+ show (DirectoryTreeElement label path isDir) = show label ++" ["++ show path ++"] "++(if isDir then "(directory)" else "(file)")++instance Eq (DirectoryTreeElement) where+ (DirectoryTreeElement label path isDir) == (DirectoryTreeElement label' path' isDir') = (label == label') && (path == path') && (isDir == isDir')++type DirectoryForest = Forest DirectoryTreeElement+type DirectoryTreeLoader = FilePath -> IO DirectoryForest+type DirectoryReader = FilePath -> IO [FilePath]+type IsDirectoryCheck = FilePath -> IO Bool++fileTreeGenerator :: DirectoryReader -> IsDirectoryCheck -> DirectoryTreeLoader+fileTreeGenerator getDirectoryContents doesDirectoryExist root = do+ directoryContents <- retrieveDirectoryContents+ forM directoryContents $ \ (name, path, isDir) -> do+ childrenForest <- if isDir then callSelf path else return []+ return $ Node (DirectoryTreeElement name path isDir) childrenForest+ where+ callSelf = fileTreeGenerator getDirectoryContents doesDirectoryExist+ removeBannedDirectories = filter (`notElem` bannedDirectories)+ addFileInfo contents =+ forM contents $ \ child -> do+ let childPath = root </> child+ isDir <- doesDirectoryExist childPath+ return (child, childPath, isDir)+ retrieveDirectoryContents = do+ contents <- getDirectoryContents root+ let filteredContents = removeBannedDirectories contents+ filteredFileInfo <- addFileInfo filteredContents+ return $ sortBy contentsSortCriteria filteredFileInfo+ bannedDirectories = [".", "..", ".git"]+ contentsSortCriteria (name1, _, isDir1) (name2, _, isDir2)+ | isDir1 && not isDir2 = LT+ | isDir2 && not isDir1 = GT+ | otherwise = compare name1 name2+
+ src/lib/Hob/Ui.hs view
@@ -0,0 +1,150 @@+module Hob.Ui (loadGui,+ getActiveEditorText,+ getActiveEditorTab,+ getEditorText,+ getActiveEditor) where++import Control.Monad.Reader+import Data.Char (intToDigit)+import Data.IORef+import Data.List (intercalate)+import Data.Monoid (mconcat)+import Data.Text (unpack)+import Graphics.UI.Gtk+import Graphics.UI.Gtk.General.CssProvider+import qualified Graphics.UI.Gtk.General.StyleContext as GtkSc+import GtkExtras.LargeTreeStore as LTS++import Hob.Command.CloseCurrentTab+import Hob.Command.FindText+import Hob.Command.FocusCommandEntry+import Hob.Command.FocusNextTab+import Hob.Command.FocusNumberedTab+import Hob.Command.FocusPreviousTab+import Hob.Command.FocusSidebar+import Hob.Command.NewTab+import Hob.Command.ReloadSidebarTree+import Hob.Command.ReplaceText+import Hob.Command.SaveCurrentTab+import Hob.Context+import Hob.Context.FileContext+import Hob.Context.StyleContext+import Hob.Context.UiContext+import Hob.Ui.CommandEntry+import Hob.Ui.Editor+import Hob.Ui.Sidebar+import Hob.Ui.SidebarSearch++loadGui :: FileContext -> StyleContext -> IO Context+loadGui fileCtx styleCtx = do+ _ <- initGUI++ builder <- loadUiBuilder+ setGtkStyle styleCtx++ ctx <- initCtx builder defaultCommands+ initMainWindow ctx+ initEditingArea ctx+ initSidebar ctx+ initCommandEntry ctx+ initActiveModesMonitor ctx+ return ctx+ where+ initCtx builder initCommands = do+ window <- builderGetObject builder castToWindow "mainWindow"+ notebook <- builderGetObject builder castToNotebook "tabbedEditArea"+ cmdEntry <- builderGetObject builder castToEntry "command"+ treeView <- builderGetObject builder castToTreeView "directoryListing"+ treeViewSearch <- builderGetObject builder castToEntry "directoryListingSearch"+ activeModesObject <- builderGetObject builder castToLabel "activeMode"+ treeModel <- LTS.treeStoreNew []+ let uiCtx = UiContext window notebook cmdEntry treeView treeViewSearch activeModesObject+ initContext styleCtx fileCtx uiCtx treeModel initCommands++ loadUiBuilder = do+ builder <- builderNew+ builderAddFromFile builder $ uiFile styleCtx+ return builder++ initSidebar ctx = do+ let treeView = sidebarTree . uiContext $ ctx+ let treeViewSearch = sidebarTreeSearch . uiContext $ ctx+ widgetSetName treeView "directoryListing"+ widgetSetName treeViewSearch "sidebarSearchEntry"+ let mainEditNotebook = mainNotebook . uiContext $ ctx+ newSideBarFileTree ctx treeView $ launchNewFileEditor ctx mainEditNotebook+ newSideBarFileTreeSearch ctx++ initCommandEntry ctx = do+ let cmdEntry = commandEntry . uiContext $ ctx+ widgetSetName cmdEntry "commandEntry"+ deferredRunner ctx $ newCommandEntry cmdEntry++ initMainWindow ctx = do+ let window = mainWindow . uiContext $ ctx+ lastPressedKeyRef <- newIORef ""+ widgetSetName window "mainWindow"+ _ <- window `on` keyPressEvent $ do+ modifier <- eventModifier+ keyT <- eventKeyName+ let key = unpack keyT+ liftIO $ writeIORef lastPressedKeyRef key+ if key == "Control_L" then return False+ else invokeKeyCommand ctx (modifier, key)+ _ <- window `on` keyReleaseEvent $ do+ modifier <- eventModifier+ keyT <- eventKeyName+ lastPressedKey <- liftIO $ readIORef lastPressedKeyRef+ let key = unpack keyT+ if (lastPressedKey == key) && (key == "Control_L") then invokeKeyCommand ctx (modifier, key)+ else return False+ return ()++ initEditingArea ctx = do+ let mainEditNotebook = mainNotebook . uiContext $ ctx+ _ <- mainEditNotebook `on` switchPage $ const $ deferredRunner ctx (emitEvent $ Event "core.editor.focused")+ return ()++ invokeKeyCommand ctx command = liftIO . runApp ctx $ do+ activeCommands <- getActiveCommands+ maybe (return False)+ (\cmd -> commandExecute cmd >> return True) $+ matchKeyBinding activeCommands command++ initActiveModesMonitor ctx = deferredRunner ctx $ do+ registerEventHandler (Event "core.editor.focused") refreshModesLabel+ registerEventHandler (Event "core.mode.change") refreshModesLabel++ refreshModesLabel = do+ activeCtx <- ask+ modes <- activeModes+ let modesUi = activeModesLabel . uiContext $ activeCtx+ let modesToString = intercalate " | " . filter (not . null) . map modeName+ liftIO $ labelSetText modesUi $ maybe "-" modesToString modes++ defaultCommands = mconcat $ [+ createMatcherForKeyBinding ([Control], "w") closeCurrentEditorTab,+ createMatcherForKeyBinding ([Control], "s") saveCurrentEditorTab,+ createMatcherForKeyBinding ([Control], "n") editNewFileCommandHandler,+ createMatcherForKeyBinding ([Control], "r") reloadSidebarTreeCommandHandler,+ createMatcherForKeyBinding ([Control], "Tab") focusNextTabCommandHandler,+ createMatcherForKeyBinding ([Shift, Control], "Tab") focusPreviousTabCommandHandler,+ createMatcherForKeyBinding ([Shift, Control], "ISO_Left_Tab") focusPreviousTabCommandHandler,+ createMatcherForKeyBinding ([Control], "t") focusSidebarCommandHandler,+ createMatcherForKeyBinding ([Shift, Control], "T") syncFocusSidebarCommandHandler,+ createMatcherForPrefix "/" searchCommandHandler,+ createMatcherForReplace 's' replaceCommandHandler,+ createMatcherForKeyBinding ([Control], "Control_L") focusCommandEntryCommandHandler,+ createMatcherForKeyBinding ([], "Escape") focusActiveEditorAndExitLastModeCommandHandler+ ] +++ [+ createMatcherForKeyBinding ([Control], [intToDigit $ (position + 1) `mod` 10]) $ focusNumberedTabCommandHandler position+ | position <- [0..9]+ ]++setGtkStyle :: StyleContext -> IO ()+setGtkStyle styleCtx = do+ cssProvider <- cssProviderNew+ cssProviderLoadFromPath cssProvider $ uiTheme styleCtx+ maybe (return()) (\screen -> GtkSc.styleContextAddProviderForScreen screen cssProvider 800) =<< screenGetDefault+
+ src/lib/Hob/Ui/CommandEntry.hs view
@@ -0,0 +1,86 @@+module Hob.Ui.CommandEntry (newCommandEntry, newCommandEntryDetached) where++import Control.Monad.Reader+import Data.IORef+import Data.Text (unpack)+import Graphics.UI.Gtk+import qualified Graphics.UI.Gtk.General.StyleContext as GtkSc++import Hob.Context+import Hob.Control++type PreviewResetState = (PreviewCommandHandler -> App(), App())++commandPreviewResetState :: App PreviewResetState+commandPreviewResetState = do+ state <- liftIO $ newIORef Nothing+ return (+ liftIO . writeIORef state . Just,+ do+ resetCommand <- liftIO $ readIORef state+ maybeDo previewReset resetCommand+ liftIO $ writeIORef state Nothing+ )++newCommandEntry :: Entry -> App ()+newCommandEntry cmdEntry = do+ ctx <- ask+ (onChange, onReturn) <- newCommandEntryDetached cmdEntry+ let liftedOn a b c = liftIO $ on a b c+ _ <- cmdEntry `liftedOn` editableChanged $ deferredRunner ctx onChange+ _ <- cmdEntry `liftedOn` keyPressEvent $ do+ modifier <- eventModifier+ key <- eventKeyName+ case (modifier, unpack key) of+ ([], "Return") -> liftIO $ deferredRunner ctx onReturn >> return True+ _ -> return False+ return ()++newCommandEntryDetached :: Entry -> App (App(), App())+newCommandEntryDetached cmdEntry = do+ previewResetState <- commandPreviewResetState+ return (onChanged previewResetState, onReturn previewResetState)+ where+ onChanged =+ previewCmd cmdEntry+ onReturn previewResetState = do+ runCmd cmdEntry previewResetState+ liftIO $ entrySetText cmdEntry ""+++previewCmd :: Entry -> PreviewResetState -> App ()+previewCmd cmdEntry (setLastPreviewCmd, dispatchLastPreviewReset) = do+ dispatchLastPreviewReset+ text <- liftIO $ entryGetText cmdEntry+ if text == "" then+ setOkStatus cmdEntry+ else do+ cmdMatcher <- getActiveCommands+ let command = matchCommand cmdMatcher text+ maybe notifyFailure handleCommand command+ where+ notifyFailure = setErrorStatus cmdEntry+ handleCommand command = do+ setOkStatus cmdEntry+ maybeDo invokePreview $ commandPreview command+ invokePreview prev = do+ previewExecute prev+ setLastPreviewCmd prev++runCmd :: Entry -> PreviewResetState -> App ()+runCmd cmdEntry (_, dispatchLastPreviewReset) = do+ dispatchLastPreviewReset+ text <- liftIO $ entryGetText cmdEntry+ cmdMatcher <- getActiveCommands+ let command = matchCommand cmdMatcher text+ maybeDo commandExecute command++setErrorStatus :: Entry -> App ()+setErrorStatus cmdEntry = do+ cmdEntryStyleContext <- liftIO $ widgetGetStyleContext cmdEntry+ liftIO $ GtkSc.styleContextAddClass cmdEntryStyleContext "error"++setOkStatus :: Entry -> App ()+setOkStatus cmdEntry = do+ cmdEntryStyleContext <- liftIO $ widgetGetStyleContext cmdEntry+ liftIO $ GtkSc.styleContextRemoveClass cmdEntryStyleContext "error"
+ src/lib/Hob/Ui/Editor.hs view
@@ -0,0 +1,217 @@+module Hob.Ui.Editor (+ newEditorForText,+ getActiveEditorText,+ getActiveEditorTab,+ getActiveEditor,+ invokeOnActiveEditor,+ getEditorText,+ getEditorFilePath,+ setEditorFilePath,+ getEditorFromNotebookTab,+ updateEditorTitle+ ) where++import Control.Monad.Reader+import Data.Text (Text)+import Filesystem.Path.CurrentOS (decodeString, encodeString, filename)+import Graphics.UI.Gtk+import Graphics.UI.Gtk.SourceView (SourceDrawSpacesFlags (..), SourceView,+ castToSourceView,+ sourceBufferBeginNotUndoableAction,+ sourceBufferEndNotUndoableAction,+ sourceBufferNew,+ sourceBufferSetHighlightSyntax,+ sourceBufferSetLanguage,+ sourceBufferSetStyleScheme,+ sourceViewNewWithBuffer,+ sourceViewSetAutoIndent,+ sourceViewSetDrawSpaces,+ sourceViewSetHighlightCurrentLine,+ sourceViewSetIndentOnTab,+ sourceViewSetIndentWidth,+ sourceViewSetInsertSpacesInsteadOfTabs,+ sourceViewSetShowLineNumbers,+ sourceViewSetTabWidth)+import System.Glib.GObject (Quark)++import Hob.Context+import Hob.Context.FileContext+import Hob.Context.StyleContext+import Hob.Context.UiContext+import Hob.Control++gtkEditor :: SourceView -> Editor+gtkEditor sourceView = Editor+ { editorId = const . liftIO $ getEditorId sourceView++ , enterEditorMode = \editor mode -> do+ modes <- liftIO $ getEditorModes sourceView+ liftIO $ setEditorModes sourceView $ modes++[mode]+ return editor++ , exitLastEditorMode = \editor -> do+ modes <- liftIO $ getEditorModes sourceView+ if null modes then return editor+ else do+ cleanup $ last modes+ liftIO $ setEditorModes sourceView $ init modes+ return editor++ , modeStack = const . liftIO $ getEditorModes sourceView++ , isCurrentlyActive = const $ do+ ctx <- ask+ active <- liftIO $ getActiveEditor ctx+ return $ active == Just sourceView+ }++newEditorForText :: Notebook -> Maybe FilePath -> Text -> App ()+newEditorForText targetNotebook filePath text = do+ ctx <- ask+ liftIO $ do+ newId <- idGenerator ctx+ editor <- createNewEditor ctx+ setEditorId editor newId+ setEditorModes editor []+ updateEditors (editors ctx) $ \oldEditors -> return $ oldEditors ++ [gtkEditor editor]+ where+ title = tabTitleForFile filePath+ setBufferLanguage buffer (Just lang) = sourceBufferSetLanguage buffer (Just lang) >> sourceBufferSetHighlightSyntax buffer True+ setBufferLanguage _ Nothing = return()+ createNewEditor ctx = do+ buffer <- sourceBufferNew Nothing+ maybeDo (setBufferLanguage buffer <=< sourceLanguage (fileContext ctx)) filePath++ sourceBufferBeginNotUndoableAction buffer+ textBufferSetText buffer text+ textBufferSetModified buffer False+ sourceBufferEndNotUndoableAction buffer++ sourceBufferSetStyleScheme buffer =<< sourceStyleScheme (styleContext ctx) filePath++ editor <- sourceViewNewWithBuffer buffer+ sourceViewSetShowLineNumbers editor True+ sourceViewSetAutoIndent editor True+ sourceViewSetIndentOnTab editor True+ sourceViewSetIndentWidth editor 4+ sourceViewSetTabWidth editor 4+ sourceViewSetInsertSpacesInsteadOfTabs editor True+ sourceViewSetHighlightCurrentLine editor True+ sourceViewSetDrawSpaces editor SourceDrawSpacesTrailing++ scrolledWindow <- scrolledWindowNew Nothing Nothing+ scrolledWindow `containerAdd` editor++ widgetModifyFont editor =<< sourceStyleFont (styleContext ctx) filePath++ widgetShowAll scrolledWindow+ tabNr <- notebookAppendPage targetNotebook scrolledWindow title+ notebookSetCurrentPage targetNotebook tabNr+ notebookSetShowTabs targetNotebook True++ _ <- buffer `on` modifiedChanged $ notebookSetTabLabelText targetNotebook scrolledWindow =<< tabTitleForEditor editor++ setEditorFilePath editor filePath+ return editor+++getActiveEditorText :: Context -> IO (Maybe Text)+getActiveEditorText ctx = do+ editor <- getActiveEditor ctx+ maybe (return Nothing) ((return . Just) <=< getEditorText) editor++getEditorText :: TextViewClass a => a -> IO Text+getEditorText textEdit = do+ textBuf <- textViewGetBuffer textEdit+ get textBuf textBufferText++getActiveEditor :: Context -> IO (Maybe SourceView)+getActiveEditor = maybe (return Nothing) getEditorFromNotebookTab <=< getActiveEditorTab++invokeOnActiveEditor :: (SourceView -> IO()) -> App ()+invokeOnActiveEditor actions = do+ ctx <- ask+ editor <- liftIO $ getActiveEditor ctx+ liftIO $ maybeDo actions editor++getEditorFromNotebookTab :: Widget -> IO (Maybe SourceView)+getEditorFromNotebookTab currentlyActiveEditor =+ if currentlyActiveEditor `isA` gTypeScrolledWindow then do+ let textEditScroller = castToScrolledWindow currentlyActiveEditor+ textEdit <- binGetChild textEditScroller+ return $ fmap castToSourceView textEdit+ else return Nothing++getActiveEditorTab :: Context -> IO (Maybe Widget)+getActiveEditorTab ctx = do+ pageNum <- notebookGetCurrentPage tabbed+ if pageNum < 0 then+ return Nothing+ else do+ tabs <- containerGetChildren tabbed+ return $ Just $ tabs!!pageNum+ where tabbed = mainNotebook.uiContext $ ctx++tabTitleForFile :: Maybe FilePath -> String+tabTitleForFile (Just filePath) = filename' filePath+ where filename' = encodeString . filename . decodeString+tabTitleForFile Nothing = "(new file)"++tabTitleForEditor :: SourceView -> IO String+tabTitleForEditor editor = do+ filePath <- getEditorFilePath editor+ buffer <- textViewGetBuffer editor+ modified <- buffer `get` textBufferModified+ return $ if modified then tabTitleForFile filePath ++ "*" else tabTitleForFile filePath++setEditorFilePath :: SourceView -> Maybe FilePath -> IO ()+setEditorFilePath editor filePath = do+ quark <- fileNameQuark+ objectSetAttribute quark editor filePath++getEditorFilePath :: SourceView -> IO (Maybe FilePath)+getEditorFilePath editor = do+ quark <- fileNameQuark+ objectGetAttributeUnsafe quark editor++setEditorId :: SourceView -> Int -> IO ()+setEditorId editor identifier = do+ quark <- editorIdQuark+ objectSetAttribute quark editor $ Just identifier++getEditorId :: SourceView -> IO Int+getEditorId editor = do+ quark <- editorIdQuark+ mRet <- objectGetAttributeUnsafe quark editor+ case mRet of+ Just ret -> return ret+ Nothing -> error "editor has no id assigned"++setEditorModes :: SourceView -> [Mode] -> IO ()+setEditorModes editor modes = do+ quark <- editorModesQuark+ objectSetAttribute quark editor $ Just modes++getEditorModes :: SourceView -> IO [Mode]+getEditorModes editor = do+ quark <- editorModesQuark+ mRet <- objectGetAttributeUnsafe quark editor+ case mRet of+ Just ret -> return ret+ Nothing -> error "editor has no modes assigned"++updateEditorTitle :: SourceView -> IO ()+updateEditorTitle editor = do+ Just scrolledW <- widgetGetParent editor+ Just notebookW <- widgetGetParent scrolledW+ let notebook = castToNotebook notebookW+ notebookSetTabLabelText notebook scrolledW =<< tabTitleForEditor editor++fileNameQuark :: IO Quark+fileNameQuark = quarkFromString "fileName"++editorIdQuark :: IO Quark+editorIdQuark = quarkFromString "editorId"++editorModesQuark :: IO Quark+editorModesQuark = quarkFromString "editorModes"
+ src/lib/Hob/Ui/Editor/Search.hs view
@@ -0,0 +1,153 @@+module Hob.Ui.Editor.Search (+ highlightSearchPreview,+ resetSearchPreview,+ findFirstFromCursor,+ findNext,+ findPrevious,+ resetSearch,+ getEditorSearchString,+ startReplace,+ replaceNext,+ resetReplace,+ ) where++import Control.Monad (when)+import Data.Text (pack)+import Graphics.UI.Gtk+import Graphics.UI.Gtk.SourceView (SourceView)+import System.Glib.GObject (Quark)++import Hob.Control++highlightSearchPreview :: SourceView -> String -> IO()+highlightSearchPreview editor text = do+ buffer <- textViewGetBuffer editor+ tagTable <- textBufferGetTagTable buffer+ tag <- maybe (addNewSearchTag tagTable) return =<< textTagTableLookup tagTable "search"+ (start, end) <- textBufferGetBounds buffer+ addNewSearchTags buffer tag start end+ where+ addNewSearchTag tagTable = do+ tag <- textTagNew $ Just $ pack "search"+ tag `set` [textTagBackground := "#707550"]+ textTagTableAdd tagTable tag+ return tag+ addNewSearchTags buffer tag start end = do+ result <- textIterForwardSearch start text [TextSearchTextOnly] (Just end)+ case result of+ Just (matchStart, matchEnd) -> do+ textBufferApplyTag buffer tag matchStart matchEnd+ addNewSearchTags buffer tag matchEnd end+ Nothing -> return()++resetSearch :: SourceView -> IO()+resetSearch editor = do+ setEditorSearchString editor Nothing+ resetSearchPreview editor++resetSearchPreview :: SourceView -> IO()+resetSearchPreview editor = do+ buffer <- textViewGetBuffer editor+ tagTable <- textBufferGetTagTable buffer+ maybeDo (removeEditorTag buffer) =<< textTagTableLookup tagTable "search"+ where+ removeEditorTag buffer tag = do+ (start, end) <- textBufferGetBounds buffer+ textBufferRemoveTag buffer tag start end++findNext :: SourceView -> IO()+findNext editor = do+ searchString <- getEditorSearchString editor+ maybeDo (searchExecute editor) searchString++findPrevious :: SourceView -> IO()+findPrevious editor = do+ searchString <- getEditorSearchString editor+ maybeDo (searchExecuteBackwards editor) searchString++findFirstFromCursor :: SourceView -> String -> IO()+findFirstFromCursor editor text = do+ setEditorSearchString editor $ Just text+ highlightSearchPreview editor text+ searchExecute editor text+++startReplace :: SourceView -> String -> String -> IO()+startReplace editor textFrom textTo = do+ findFirstFromCursor editor textFrom+ setEditorReplaceString editor $ Just textTo++replaceNext :: SourceView -> IO()+replaceNext editor = do+ maybeDo replaceSelectionWith =<< getEditorReplaceString editor+ findNext editor+ where+ replaceSelectionWith replaceText = maybeDo (replaceSearchSelectionWith replaceText) =<< getEditorSearchString editor+ replaceSearchSelectionWith replaceText searchText = do+ buffer <- textViewGetBuffer editor+ (s, e) <- textBufferGetSelectionBounds buffer+ selectedText <- textBufferGetText buffer s e False+ when (searchText == selectedText) $ do+ textBufferDelete buffer s e+ textBufferInsert buffer s replaceText++resetReplace :: SourceView -> IO()+resetReplace editor = do+ resetSearch editor+ setEditorReplaceString editor Nothing+++searchExecute :: SourceView -> String -> IO()+searchExecute editor text = do+ buffer <- textViewGetBuffer editor+ (_, start) <- textBufferGetSelectionBounds buffer+ maybe (retryFromStart buffer) (selectMatch editor buffer) =<< findNextResult start+ where+ findNextResult start = textIterForwardSearch start text [TextSearchTextOnly] Nothing+ retryFromStart buffer = do+ (start, _) <- textBufferGetBounds buffer+ maybeDo (selectMatch editor buffer) =<< findNextResult start++searchExecuteBackwards :: SourceView -> String -> IO()+searchExecuteBackwards editor text = do+ buffer <- textViewGetBuffer editor+ (end, _) <- textBufferGetSelectionBounds buffer+ maybe (retryFromEnd buffer) (selectMatch editor buffer) =<< findPreviousResult end+ where+ findPreviousResult end = textIterBackwardSearch end text [TextSearchTextOnly] Nothing+ retryFromEnd buffer = do+ (_, end) <- textBufferGetBounds buffer+ maybeDo (selectMatch editor buffer) =<< findPreviousResult end++selectMatch :: (TextViewClass tv, TextBufferClass tb) => tv -> tb -> (TextIter, TextIter) -> IO ()+selectMatch editor buffer (start, end) = do+ textBufferSelectRange buffer start end+ caretMark <- textBufferGetInsert buffer+ textViewScrollToMark editor caretMark 0.1 Nothing++setEditorSearchString :: SourceView -> Maybe String -> IO ()+setEditorSearchString editor searchString = do+ quark <- searchStringQuark+ objectSetAttribute quark editor searchString++getEditorSearchString :: SourceView -> IO (Maybe String)+getEditorSearchString editor = do+ quark <- searchStringQuark+ objectGetAttributeUnsafe quark editor++searchStringQuark :: IO Quark+searchStringQuark = quarkFromString "activeSearchString"++setEditorReplaceString :: SourceView -> Maybe String -> IO ()+setEditorReplaceString editor replaceString = do+ quark <- replaceStringQuark+ objectSetAttribute quark editor replaceString++getEditorReplaceString :: SourceView -> IO (Maybe String)+getEditorReplaceString editor = do+ quark <- replaceStringQuark+ objectGetAttributeUnsafe quark editor++replaceStringQuark :: IO Quark+replaceStringQuark = quarkFromString "activeReplaceString"+
+ src/lib/Hob/Ui/Sidebar.hs view
@@ -0,0 +1,108 @@+module Hob.Ui.Sidebar (+ newSideBarFileTree,+ reloadSidebarTree,+ activateSidebarPath,+ syncPathToSidebar,+ nameColumn,+ pathColumn+ ) where++import Control.Monad.Reader+import Data.List (isPrefixOf)+import Graphics.UI.Gtk+import Graphics.UI.Gtk.ModelView as Mv+import GtkExtras.LargeTreeStore as LTS++import Hob.Command.NewTab+import Hob.Context+import Hob.Context.FileContext+import Hob.Context.UiContext+import Hob.Control+import Hob.DirectoryTree++newSideBarFileTree :: Context -> TreeView -> NewFileEditorLauncher -> IO ()+newSideBarFileTree ctx treeView launchFile = do+ let treeStore = fileTreeStore ctx+ runApp ctx reloadSidebarTree+ initNameColumn treeStore++ treeViewSetHeadersVisible treeView False+ treeViewSetEnableSearch treeView False+ treeViewSetModel treeView treeStore++ _ <- treeView `on` rowCollapsed $ \ _ _ -> treeViewColumnsAutosize treeView+ _ <- treeView `on` rowActivated $ \ path _ -> activateRow path =<< LTS.treeStoreGetValue treeStore path++ return ()++ where+ initNameColumn treeStore = do+ customStoreSetColumn treeStore nameColumn elementLabel+ customStoreSetColumn treeStore pathColumn elementPath++ col <- treeViewColumnNew++ rend <- Mv.cellRendererTextNew+ Mv.cellLayoutPackStart col rend True+ Mv.cellLayoutSetAttributes col rend treeStore (\v -> [Mv.cellText := elementLabel v])++ _ <- treeViewAppendColumn treeView col+ return ()++ activateRow :: TreePath -> DirectoryTreeElement -> IO ()+ activateRow path el = if isDirectory el then void $ treeViewExpandRow treeView path False+ else launchFile . elementPath $ el+++nameColumn :: ColumnId row String+nameColumn = makeColumnIdString 0++pathColumn :: ColumnId row FilePath+pathColumn = makeColumnIdString 1++reloadSidebarTree :: App ()+reloadSidebarTree = do+ ctx <- ask+ let treeStore = fileTreeStore ctx+ let fileCtx = fileContext ctx+ let fileTreeLoader = contextFileTreeLoader fileCtx+ liftIO $ LTS.treeStoreClear treeStore+ liftIO $ LTS.treeStoreInsertForest treeStore [] 0 =<< fileTreeLoader+ emitEvent $ Event "core.sidebar.reload"+++activateSidebarPath :: TreeViewClass tv => tv -> TreePath -> IO ()+activateSidebarPath treeView path = do+ treeViewCollapseAll treeView+ treeViewExpandToPath treeView path+ treeViewSetCursor treeView path Nothing+++++syncPathToSidebar :: FilePath -> App()+syncPathToSidebar filePath = do+ ctx <- ask+ let treeView = sidebarTree.uiContext $ ctx+ liftIO (maybeDo (syncTreeViewModel treeView) =<< treeViewGetModel treeView)+ where+ syncTreeViewModel treeView model = do+ mStartIter <- treeModelGetIterFirst model+ maybeDo (syncToMatchingPath treeView model) mStartIter+ syncToMatchingPath treeView model startingIter =+ maybeDo (syncToIter treeView model) =<< findFilePath model filePath startingIter+ syncToIter treeView model iter = activateSidebarPath treeView =<< treeModelGetPath model iter++findFilePath :: TreeModelClass self =>+ self -> FilePath -> TreeIter -> IO (Maybe TreeIter)+findFilePath model filePath iter = do+ path <- treeModelGetValue model iter pathColumn+ if path == filePath then return $ Just iter+ else if (path++"/") `isPrefixOf` filePath then matchChildren+ else matchNextSibling+ where matchChildren = recurseToMaybeIter =<< treeModelIterChildren model iter+ matchNextSibling = recurseToMaybeIter =<< treeModelIterNext model iter+ recurseToMaybeIter Nothing = return Nothing+ recurseToMaybeIter (Just it) = findFilePath model filePath it++
+ src/lib/Hob/Ui/SidebarSearch.hs view
@@ -0,0 +1,349 @@+module Hob.Ui.SidebarSearch (+ newSideBarFileTreeSearch,+ startSidebarSearch,+ updateSidebarSearch,+ continueSidebarSearch,+ continueSidebarSearchBackwards,+ initFileTreeIndex,+ ) where++import Control.Concurrent.MVar (newMVar, readMVar,+ swapMVar)+import Control.Monad.Reader+import Data.Char (isPrint, toLower)+import Data.List (isPrefixOf, sortBy)+import Data.Maybe+import Data.Text (unpack)+import Data.Tree+import qualified Data.Vector as V+import Graphics.UI.Gtk+import Graphics.UI.Gtk.General.StyleContext (styleContextAddClass,+ styleContextRemoveClass)++import Hob.Context+import Hob.Context.FileContext+import Hob.Context.UiContext+import Hob.Control+import Hob.DirectoryTree+import Hob.Ui.Sidebar++{-| Index based on suffix arrays++The two vectors contain the path element surrounded by slashes '/'+and a sorted symbol positions respectively. The index is generated+by a function 'mkIndex'.++Example:++@+mkIndex "example"+LetterIndex (fromList "/example/") (fromList [0,8,3,1,7,6,4,5,2])+@+-}+data LetterIndex = LetterIndex (V.Vector Char) (V.Vector Int) deriving Show+data SearchIndexNode a = PathNode LetterIndex a (SearchIndex a) | LeafNode LetterIndex a deriving Show+type SearchIndex a = [SearchIndexNode a]++instance Eq a => Eq (SearchIndexNode a) where+ (LeafNode _ a) == (LeafNode _ b) = a == b+ (PathNode _ a _) == (PathNode _ b _) = a == b+ _ == _ = False++type DirectorySearchIndex = SearchIndex DirectoryTreeElement++mkIndex :: String -> LetterIndex+mkIndex s = LetterIndex word indices+ where+ word = V.fromList . map toLower $ '/':s++"/"+ indices = V.fromList . sortBy indexOrdering . take (V.length word) $ [0..]+ indexOrdering i1 i2 = let c1 = word V.! i1+ c2 = word V.! i2+ cmp = compare c1 c2+ in if cmp == EQ then compare i1 i2 else cmp++{-| Find all positions for a character -}+findOccurrences :: LetterIndex -> Char -> [Int]+findOccurrences (LetterIndex word idx) c = range mid+ where+ binSearch low high+ | low > high = Nothing+ | value > c = binSearch low (middle-1)+ | value < c = binSearch (middle+1) high+ | otherwise = Just middle+ where+ value = word V.! (idx V.! middle)+ middle = (low + high) `quot` 2++ mid = binSearch 0 (highBound-1)++ startFrom x+ | x < 0 = 0+ | otherwise = if (word V.! (idx V.! x)) == c then startFrom (x-1) else x+1++ endFrom x+ | x == highBound = highBound - 1+ | otherwise = if (word V.! (idx V.! x)) == c then endFrom (x+1) else x-1++ range Nothing = []+ range (Just x) = V.toList . V.slice s (e-s+1) $ idx+ where+ e = endFrom x+ s = startFrom x+ highBound = V.length word++{-| Match query against the index++A query is a list for strings.+Each string is matched as a substring of the given index.+Then the next query string is matched.+Once there is a match failure, the rest of the query is returned as the result.++Example:++@+matchQuery (mkIndex "example") ["/ex", "ple"] = []+matchQuery (mkIndex "example") ["/ex", "pla"] = ["pla"]+matchQuery (mkIndex "example") ["/ex", "pla", "the rest"] = ["pla", "the rest"]+@+-}+matchQuery :: LetterIndex -> [String] -> [String]+matchQuery index@(LetterIndex word _) = match 0+ where+ match _ [] = []+ match from ([]:qs) = match from qs+ match from (q:qs)+ | from > highBound = q:qs+ | otherwise = if null subMatches then q:qs+ else let from' = head subMatches+ in match from' qs++ where+ subMatches = mapMaybe (`matchSubString` q) $ findPossibleStarts from q++ findPossibleStarts _ [] = []+ findPossibleStarts from (c:_) = filter (>=from) . findOccurrences index $ c++ matchSubString from [] = Just from+ matchSubString from (c:cs)+ | from > highBound = Nothing+ | (word V.! from) == c = matchSubString (from+1) cs+ | otherwise = Nothing++ highBound = V.length word - 1++buildIndex :: Forest DirectoryTreeElement -> DirectorySearchIndex+buildIndex = fmap addNode+ where+ addNode Node{rootLabel=element, subForest=children} = if isDirectory element then pathNode else leafNode+ where+ pathNode = PathNode index element (buildIndex children)+ leafNode = LeafNode index element+ index = mkIndex $ elementLabel element++findNextMatch :: DirectorySearchIndex -> FilePath -> [String] -> Maybe DirectoryTreeElement+findNextMatch index previous = findMatch $ filterFromPath index previous++findPreviousMatch :: DirectorySearchIndex -> FilePath -> [String] -> Maybe DirectoryTreeElement+findPreviousMatch index next = findMatch $ filterFromPath (reverseIndex index) next+ where+ reverseIndex = map reverseNode . reverse+ where+ reverseNode n@(LeafNode _ _) = n+ reverseNode (PathNode letterIdx el children) = PathNode letterIdx el $ reverseIndex children++filterFromPath :: DirectorySearchIndex -> FilePath -> DirectorySearchIndex+filterFromPath [] _ = []+filterFromPath (node@(LeafNode _ el):is) path+ | elementPath el == path = node:is+ | otherwise = filterFromPath is path+filterFromPath (node@(PathNode lidx el children):is) path+ | elementPath el == path = node:is+ | (elementPath el ++ "/") `isPrefixOf` path = PathNode lidx el (filterFromPath children path) : is+ | otherwise = filterFromPath is path+++findMatch :: DirectorySearchIndex -> [String] -> Maybe DirectoryTreeElement+findMatch [] _ = Nothing+findMatch (LeafNode idx el : is) queries+ | matchSuccess = Just el+ | otherwise = findMatch is queries+ where matchSuccess = null $ matchQuery idx queries+findMatch (PathNode idx _ children : is) queries = mplus childrenMatch $ findMatch is queries+ where childrenMatch = findMatch children $ matchQuery idx queries++{-| Prepare the query string++Parse the query into a query for matching.++Example:+@+prepareQueries "example" = ["example"]+prepareQueries "exam ple" = ["exam","ple"]+prepareQueries "exam/ple" = ["exam/","/ple"]+prepareQueries "exam//ple" = ["exam/","/","/ple"]+prepareQueries "exam/ ple" = ["exam/","ple"]+@+-}+prepareQueries :: String -> [String]+prepareQueries = concatMap breakSlashes . breakSpaces . map toLower+ where+ breakSpaces s = case break (== ' ') s of+ ([], []) -> []+ (a, []) -> [a]+ ([], ' ':b) -> breakSpaces b+ (a, ' ':b) -> a : breakSpaces b+ (a, b) -> a : breakSpaces b+ breakSlashes s = case break (== '/') s of+ ([], []) -> []+ (a, []) -> [a]+ ([], '/':b) -> prependToFirst '/' $ breakSlashes b+ (a, '/':b) -> (a++"/") : prependToFirst '/' (breakSlashes b)+ (a, b) -> (a++"/") : prependToFirst '/' (breakSlashes b)+ prependToFirst _ [] = []+ prependToFirst a ([]:xs) = [a]:xs+ prependToFirst a (x@(q:_):xs)+ | a == q = [a]:x:xs+ | otherwise = (a:x):xs++newSideBarFileTreeSearch :: Context -> IO ()+newSideBarFileTreeSearch ctx = do+ let treeView = sidebarTree.uiContext $ ctx+ let searchEntry = sidebarTreeSearch.uiContext $ ctx+ index <- newMVar =<< runApp ctx initFileTreeIndex+ runApp ctx $ registerEventHandler (Event "core.sidebar.reload") (initFileTreeIndex >>= (liftIO . swapMVar index) >> return())+ _ <- treeView `on` keyPressEvent $ do+ key <- eventKeyVal+ maybe (return False) startSearch $ keyToChar key+ _ <- searchEntry `on` editableChanged $ runApp ctx $ liftIO (readMVar index) >>= updateSidebarSearch+ _ <- searchEntry `on` focusOutEvent $ liftIO $ widgetHide searchEntry >> return False+ _ <- searchEntry `on` keyPressEvent $ do+ modifier <- eventModifier+ if Prelude.null modifier then do+ key <- eventKeyName+ case unpack key of+ "Down" -> liftIO $ runApp ctx $ liftIO (readMVar index) >>= continueSidebarSearch >> return True+ "Up" -> liftIO $ runApp ctx $ liftIO (readMVar index) >>= continueSidebarSearchBackwards >> return True+ "Return" -> stopSearchAndActivateResult treeView searchEntry+ _ -> return False+ else return False+ return ()+ where+ startSearch firstChar+ | isPrint firstChar = liftIO $ do+ startSidebarSearch ctx [firstChar]+ return True+ | otherwise = return False+ stopSearchAndActivateResult treeView searchEntry = liftIO $ do+ widgetGrabFocus treeView+ widgetHide searchEntry+ (path, _) <- treeViewGetCursor treeView+ column <- treeViewGetColumn treeView 0+ maybeDo (treeViewRowActivated treeView path) column+ return True++initFileTreeIndex :: App DirectorySearchIndex+initFileTreeIndex = do+ fileCtx <- fromContext fileContext+ nodeForest <- liftIO $ contextFileTreeLoader fileCtx+ return $ buildIndex nodeForest++startSidebarSearch :: Context -> String -> IO ()+startSidebarSearch ctx searchString = do+ let entry = sidebarTreeSearch.uiContext $ ctx+ sidebar = sidebarTree . uiContext $ ctx+ len = length searchString+ treeViewSetCursor sidebar [] Nothing+ entrySetText entry ""+ entrySetText entry searchString+ widgetShow entry+ widgetGrabFocus entry+ editableSelectRegion entry len len++updateSidebarSearch :: DirectorySearchIndex -> App ()+updateSidebarSearch index = invokeOnTreeViewAndModel $ continueSearch index selectNextMatch iterOnSelection+ where+ iterOnSelection treeView model = do+ (path, _) <- liftIO $ treeViewGetCursor treeView+ selectedIter <- liftIO $ treeModelGetIter model path+ maybe (treeModelGetIterFirst model) (return.Just) selectedIter++continueSidebarSearch :: DirectorySearchIndex -> App ()+continueSidebarSearch index = invokeOnTreeViewAndModel $ continueSearch index selectNextMatch iterAfterSelection+ where+ iterAfterSelection treeView model = do+ (path, _) <- treeViewGetCursor treeView+ currentIter <- treeModelGetIter model path+ maybe (return Nothing) (findNextSubtree model) currentIter++continueSidebarSearchBackwards :: DirectorySearchIndex -> App ()+continueSidebarSearchBackwards index = invokeOnTreeViewAndModel $ continueSearch index selectPreviousMatch iterBeforeSelection+ where+ iterBeforeSelection treeView model = do+ (path, _) <- treeViewGetCursor treeView+ currentIter <- treeModelGetIter model path+ maybe (return Nothing) (findPreviousSubtree model) currentIter+++continueSearch :: t2 -> (t2 -> t3 -> Entry -> String -> a -> App()) -> (t1 -> t3 -> IO (Maybe a)) -> t1 -> t3 -> App()+continueSearch index selectMatch selectionIter treeView model = do+ ctx <- ask+ let searchEntry = sidebarTreeSearch.uiContext $ ctx+ searchString <- liftIO $ entryGetText searchEntry+ maybeFirstIter <- liftIO $ selectionIter treeView model+ maybeDo (selectMatch index model searchEntry searchString) maybeFirstIter++invokeOnTreeViewAndModel :: (TreeView -> TreeModel -> App ()) -> App ()+invokeOnTreeViewAndModel fnc = do+ ctx <- ask+ let treeView = sidebarTree.uiContext $ ctx+ model <- liftIO $ treeViewGetModel treeView+ maybeDo (fnc treeView) model++selectNextMatch :: (TreeModelClass tm, EntryClass e) => DirectorySearchIndex -> tm -> e -> String -> TreeIter -> App ()+selectNextMatch index treeModel searchEntry searchString currentIter = do+ path <- liftIO $ treeModelGetValue treeModel currentIter pathColumn+ case findNextMatch index path (prepareQueries searchString) of+ Just match -> do+ liftIO $ unsetErrorState searchEntry+ syncPathToSidebar $ elementPath match+ Nothing -> liftIO $ setErrorState searchEntry++selectPreviousMatch :: (TreeModelClass tm, EntryClass e) => DirectorySearchIndex -> tm -> e -> String -> TreeIter -> App ()+selectPreviousMatch index treeModel searchEntry searchString currentIter = do+ path <- liftIO $ treeModelGetValue treeModel currentIter pathColumn+ case findPreviousMatch index path (prepareQueries searchString) of+ Just match -> do+ liftIO $ unsetErrorState searchEntry+ syncPathToSidebar $ elementPath match+ Nothing -> liftIO $ setErrorState searchEntry++setErrorState :: EntryClass e => e -> IO ()+setErrorState searchEntry = do+ widgetStyleContext <- widgetGetStyleContext searchEntry+ styleContextAddClass widgetStyleContext "error"++unsetErrorState :: EntryClass e => e -> IO ()+unsetErrorState searchEntry = do+ widgetStyleContext <- widgetGetStyleContext searchEntry+ styleContextRemoveClass widgetStyleContext "error"++findNextSubtree :: TreeModelClass treeModel => treeModel -> TreeIter -> IO (Maybe TreeIter)+findNextSubtree model iter = do+ next <- treeModelIterNext model iter+ if isJust next then return next+ else maybe (return Nothing) (findNextSubtree model) =<< treeModelIterParent model iter++findPreviousSubtree :: TreeModelClass treeModel => treeModel -> TreeIter -> IO (Maybe TreeIter)+findPreviousSubtree model iter = do+ prev <- treeModelIterPrevious model iter+ if isJust prev then return prev+ else maybe (return Nothing) (findPreviousSubtree model) =<< treeModelIterParent model iter++treeModelIterPrevious :: TreeModelClass treeModel => treeModel -> TreeIter -> IO (Maybe TreeIter)+treeModelIterPrevious model iter = do+ parent <- treeModelIterParent model iter+ currentPath <- treeModelGetPath model iter+ let nth = last currentPath+ if nth > 0 then treeModelIterNthChild model parent (nth-1)+ else return Nothing+
+ test/Hob/Command/CloseCurrentTabSpec.hs view
@@ -0,0 +1,35 @@+module Hob.Command.CloseCurrentTabSpec (main, spec) where++import Test.Hspec++import Graphics.UI.Gtk++import Hob.Command.CloseCurrentTab+import Hob.Command.NewTab (launchNewFileEditor)+import Hob.Context+import qualified Hob.Context.UiContext as HC++import HobTest.Context.Stubbed+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "close current tab command" $+ it "closes the currently active editor tab" $ do+ ctx <- loadStubbedContext+ launchEditorTab ctx "/xxx/testName.hs"+ runCtxActions ctx $ commandExecute closeCurrentEditorTab+ pagesAfterActivatingDirectory <- getNumberOfEditorPages ctx+ pagesAfterActivatingDirectory `shouldBe` 0++launchEditorTab :: Context -> String -> IO ()+launchEditorTab ctx file = do+ let notebook = HC.mainNotebook . uiContext $ ctx+ launchNewFileEditor ctx notebook file++getNumberOfEditorPages :: Context -> IO Int+getNumberOfEditorPages = notebookGetNPages . HC.mainNotebook . uiContext+
+ test/Hob/Command/FindTextSpec.hs view
@@ -0,0 +1,70 @@+module Hob.Command.FindTextSpec (main, spec) where++import Control.Monad.State (liftIO)+import Data.IORef+import Data.Maybe+import Data.Text (pack)+import Graphics.UI.Gtk+import Test.Hspec++import Hob.Command.FindText+import Hob.Context+import qualified Hob.Context.UiContext as HC+import Hob.Ui (getActiveEditor)+import Hob.Ui.Editor (newEditorForText)++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "search command handler" $ do+ it "focuses editor on execute" $ do+ (ctx, _) <- loadGuiAndExecuteSearch+ editorFocused <- widgetGetIsFocus . fromJust =<< getActiveEditor ctx+ editorFocused `shouldBe` True++ it "enters the search mode" $ do+ (ctx, _) <- loadGuiAndExecuteSearch+ ref <- newIORef Nothing+ runCtxActions ctx $ activeModes >>= (liftIO . writeIORef ref)+ modes <- readIORef ref+ (modeName . last . fromJust) modes `shouldBe` "search"++ describe "search reset command on mode exit" $+ it "stops the next search" $ do+ (ctx, buffer) <- loadGuiAndExecuteSearch+ runCtxActions ctx exitLastMode+ runCtxActions ctx $ commandExecute searchNextCommandHandler+ (start, end) <- getSelectionOffsets buffer+ (start, end) `shouldBe` (0, 4)++loadGuiAndPreviewSearch :: IO (Context, TextBuffer)+loadGuiAndPreviewSearch = do+ ctx <- loadDefaultContext+ let notebook = HC.mainNotebook . uiContext $ ctx+ runCtxActions ctx $ newEditorForText notebook Nothing $ pack "text - initial text! text"+ mEditor <- getActiveEditor ctx+ let editor = fromJust mEditor+ runCtxActions ctx $ (previewExecute . fromJust . commandPreview) (searchCommandHandler "text")+ buffer <- textViewGetBuffer editor+ return (ctx, buffer)++loadGuiAndExecuteSearch :: IO (Context, TextBuffer)+loadGuiAndExecuteSearch = do+ (ctx, buffer) <- loadGuiAndPreviewSearch+ runCtxActions ctx $ (previewReset . fromJust . commandPreview) (searchCommandHandler "text")+ iterBufferStart <- textBufferGetIterAtOffset buffer 0+ textBufferSelectRange buffer iterBufferStart iterBufferStart+ runCtxActions ctx $ commandExecute (searchCommandHandler "text")+ return (ctx, buffer)++getSelectionOffsets :: TextBuffer -> IO (Int, Int)+getSelectionOffsets buffer = do+ (iterStart, iterEnd) <- textBufferGetSelectionBounds buffer+ start <- textIterGetOffset iterStart+ end <- textIterGetOffset iterEnd+ return (start, end)
+ test/Hob/Command/FocusCommandEntrySpec.hs view
@@ -0,0 +1,51 @@+module Hob.Command.FocusCommandEntrySpec (main, spec) where++import Data.Maybe+import Graphics.UI.Gtk++import Hob.Command.FocusCommandEntry+import Hob.Command.NewTab+import Hob.Context+import qualified Hob.Context.UiContext as HC+import Hob.Ui++import Test.Hspec++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "focus command entry command" $ do+ it "focuses the command entry" $ do+ ctx <- loadDefaultContext+ focused <- toggleFocusOnCommandEntryAndReturnState ctx+ focused `shouldBe` True++ it "focus stays on toggle if there is no editor to focus to" $ do+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute toggleFocusOnCommandEntryCommandHandler+ focused <- toggleFocusOnCommandEntryAndReturnState ctx+ focused `shouldBe` True++ it "focus moves to editor on toggle" $ do+ ctx <- launchNewFile+ runCtxActions ctx $ commandExecute toggleFocusOnCommandEntryCommandHandler+ commandFocused <- toggleFocusOnCommandEntryAndReturnState ctx+ editorFocused <- widgetGetIsFocus . fromJust =<< getActiveEditor ctx+ commandFocused `shouldBe` False+ editorFocused `shouldBe` True++launchNewFile :: IO Context+launchNewFile = do+ ctx <- loadDefaultContext+ runCtxActions ctx editNewFile+ return ctx++toggleFocusOnCommandEntryAndReturnState :: Context -> IO Bool+toggleFocusOnCommandEntryAndReturnState ctx = do+ runCtxActions ctx $ commandExecute toggleFocusOnCommandEntryCommandHandler+ widgetGetIsFocus $ HC.commandEntry . uiContext $ ctx
+ test/Hob/Command/FocusNextTabSpec.hs view
@@ -0,0 +1,54 @@+module Hob.Command.FocusNextTabSpec (main, spec) where++import Control.Monad (replicateM_)+import Graphics.UI.Gtk++import Hob.Command.FocusNextTab+import Hob.Command.NewTab+import Hob.Context+import qualified Hob.Context.UiContext as HC++import Test.Hspec++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "focus next tab command" $ do+ it "does not change the state if there are no tabs" $ do+ ctx <- loadGuiWithNTabs 0+ currentPage <- focusNextTab ctx+ currentPage `shouldBe` -1++ it "leaves the first tab focused if there is just one tab" $ do+ ctx <- loadGuiWithNTabs 1+ currentPage <- focusNextTab ctx+ currentPage `shouldBe` 0++ it "focuses the next tab" $ do+ ctx <- loadGuiWithNTabs 2+ notebookSetCurrentPage (HC.mainNotebook . uiContext $ ctx) 0+ currentPage <- focusNextTab ctx+ currentPage `shouldBe` 1++ it "focuses the first tab if the command is invoked on the last tab" $ do+ ctx <- loadGuiWithNTabs 2+ notebookSetCurrentPage (HC.mainNotebook . uiContext $ ctx) 1+ currentPage <- focusNextTab ctx+ currentPage `shouldBe` 0++focusNextTab :: Context -> IO Int+focusNextTab ctx = do+ runCtxActions ctx $ commandExecute focusNextTabCommandHandler+ let notebook = HC.mainNotebook . uiContext $ ctx+ notebookGetCurrentPage notebook++loadGuiWithNTabs :: Int -> IO Context+loadGuiWithNTabs n = do+ ctx <- loadDefaultContext+ replicateM_ n $ runCtxActions ctx editNewFile+ return ctx
+ test/Hob/Command/FocusNumberedTabSpec.hs view
@@ -0,0 +1,43 @@+module Hob.Command.FocusNumberedTabSpec (main, spec) where++import Control.Monad (replicateM_)+import Graphics.UI.Gtk++import Hob.Command.FocusNumberedTab+import Hob.Command.NewTab+import Hob.Context+import qualified Hob.Context.UiContext as HC++import Test.Hspec++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "focus numbered tab command" $ do+ it "does not change the state if there is no matching tab" $ do+ ctx <- loadGuiWithNTabs 0+ currentPage <- focusNumberedTab 2 ctx+ currentPage `shouldBe` -1++ it "focuses the numbered tab" $ do+ ctx <- loadGuiWithNTabs 3+ notebookSetCurrentPage (HC.mainNotebook . uiContext $ ctx) 0+ currentPage <- focusNumberedTab 2 ctx+ currentPage `shouldBe` 2++focusNumberedTab :: Int -> Context -> IO Int+focusNumberedTab nr ctx = do+ runCtxActions ctx $ commandExecute (focusNumberedTabCommandHandler nr)+ let notebook = HC.mainNotebook . uiContext $ ctx+ notebookGetCurrentPage notebook++loadGuiWithNTabs :: Int -> IO Context+loadGuiWithNTabs n = do+ ctx <- loadDefaultContext+ replicateM_ n $ runCtxActions ctx editNewFile+ return ctx
+ test/Hob/Command/FocusPreviousTabSpec.hs view
@@ -0,0 +1,54 @@+module Hob.Command.FocusPreviousTabSpec (main, spec) where++import Control.Monad (replicateM_)+import Graphics.UI.Gtk++import Hob.Command.FocusPreviousTab+import Hob.Command.NewTab+import Hob.Context+import qualified Hob.Context.UiContext as HC++import Test.Hspec++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "focus previous tab command" $ do+ it "does not change the state if there are no tabs" $ do+ ctx <- loadGuiWithNTabs 0+ currentPage <- focusPreviousTab ctx+ currentPage `shouldBe` -1++ it "leaves the first tab focused if there is just one tab" $ do+ ctx <- loadGuiWithNTabs 1+ currentPage <- focusPreviousTab ctx+ currentPage `shouldBe` 0++ it "focuses the previous tab" $ do+ ctx <- loadGuiWithNTabs 2+ notebookSetCurrentPage (HC.mainNotebook . uiContext $ ctx) 1+ currentPage <- focusPreviousTab ctx+ currentPage `shouldBe` 0++ it "focuses the last tab if the command is invoked on the first tab" $ do+ ctx <- loadGuiWithNTabs 2+ notebookSetCurrentPage (HC.mainNotebook . uiContext $ ctx) 0+ currentPage <- focusPreviousTab ctx+ currentPage `shouldBe` 1++focusPreviousTab :: Context -> IO Int+focusPreviousTab ctx = do+ runCtxActions ctx $ commandExecute focusPreviousTabCommandHandler+ let notebook = HC.mainNotebook . uiContext $ ctx+ notebookGetCurrentPage notebook++loadGuiWithNTabs :: Int -> IO Context+loadGuiWithNTabs n = do+ ctx <- loadDefaultContext+ replicateM_ n $ runCtxActions ctx editNewFile+ return ctx
+ test/Hob/Command/FocusSidebarSpec.hs view
@@ -0,0 +1,55 @@+module Hob.Command.FocusSidebarSpec (main, spec) where++import Graphics.UI.Gtk++import Hob.Command.FocusSidebar+import Hob.Context+import qualified Hob.Context.UiContext as HC++import Test.Hspec++import HobTest.Context.Default+import HobTest.Context.Stubbed+import HobTest.Control+import HobTest.Editor++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "focus sidebar" $ do+ it "focuses the sidebar" $ do+ ctx <- loadDefaultContext+ focused <- focusSidebarAndReturnState ctx+ focused `shouldBe` True++ it "can sync the open editor path in sidebar" $ do+ ctx <- loadStubbedContext+ launchEditorTab ctx "/xxx/a/b"+ path <- syncSidebarAndReturnSelectedPath ctx+ focused <- sidebarFocusState ctx+ path `shouldBe` [0, 0]+ focused `shouldBe` True++ it "can sync the open editor path in sidebar when there is a directory named as the file's basename" $ do+ ctx <- loadStubbedContext+ launchEditorTab ctx "/xxx/a.b"+ path <- syncSidebarAndReturnSelectedPath ctx+ focused <- sidebarFocusState ctx+ path `shouldBe` [1]+ focused `shouldBe` True++sidebarFocusState :: Context -> IO Bool+sidebarFocusState = widgetGetIsFocus . HC.sidebarTree . uiContext++focusSidebarAndReturnState :: Context -> IO Bool+focusSidebarAndReturnState ctx = do+ runCtxActions ctx $ commandExecute focusSidebarCommandHandler+ sidebarFocusState ctx++syncSidebarAndReturnSelectedPath :: Context -> IO TreePath+syncSidebarAndReturnSelectedPath ctx = do+ runCtxActions ctx $ commandExecute syncFocusSidebarCommandHandler+ pos <- treeViewGetCursor . HC.sidebarTree . uiContext $ ctx+ return $ fst pos
+ test/Hob/Command/NewTabSpec.hs view
@@ -0,0 +1,35 @@+module Hob.Command.NewTabSpec (main, spec) where++import Test.Hspec++import Graphics.UI.Gtk++import qualified Hob.Context as HC+import qualified Hob.Context.UiContext as HC++import HobTest.Context.Stubbed+import HobTest.Editor++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "new tab command" $ do+ it "creates a new unnamed file" $ do+ ctx <- launchNewFile+ pagesAfterActivatingDirectory <- getNumberOfEditorPages ctx+ pagesAfterActivatingDirectory `shouldBe` 1++ it "focuses the tab with the open file if requested to open an already loaded file" $ do+ ctx <- loadStubbedContext+ let notebook = HC.mainNotebook . HC.uiContext $ ctx+ launchEditorTab ctx "/xxx/testName.hs"+ currentPageOfFirstLoadedFile <- notebookGetCurrentPage notebook+ launchEditorTab ctx "/xxx/c"+ pagesBeforeOpeningExistingFile <- notebookGetNPages notebook+ launchEditorTab ctx "/xxx/testName.hs"+ currentPageAfterLoadingTheFirstLoadedFile <- notebookGetCurrentPage notebook+ pagesAfterOpeningExistingFile <- notebookGetNPages notebook+ pagesAfterOpeningExistingFile `shouldBe` pagesBeforeOpeningExistingFile+ currentPageAfterLoadingTheFirstLoadedFile `shouldBe` currentPageOfFirstLoadedFile
+ test/Hob/Command/ReloadSidebarTreeSpec.hs view
@@ -0,0 +1,69 @@+module Hob.Command.ReloadSidebarTreeSpec (main, spec) where++import Data.Maybe+import Data.Tree+import Graphics.UI.Gtk++import Hob.Command.ReloadSidebarTree+import Hob.Context+import qualified Hob.Context.FileContext as HFC+import qualified Hob.Context.UiContext as HC+import Hob.DirectoryTree++import Test.Hspec++import HobTest.Context.Stubbed+import HobTest.Control+import HobTest.Sidebar++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "reload sidebar tree command" $ do+ it "loads new items in the tree" $ do+ ctx <- loadStubbedContext+ values <- getDirectoryListingSidebarRootItems ctx+ values `shouldBe` ["a", "a.b", "c", "-"]+ let ctx' = replaceStubbedTree ctx+ runCtxActions ctx' $ commandExecute reloadSidebarTreeCommandHandler+ values' <- getDirectoryListingSidebarRootItems ctx'+ values' `shouldBe` ["b","c"]++ it "reload sidebar search index" $ do+ ctx <- loadStubbedContext+ cursorShouldBeOnAfterSearch ctx "/new/" []+ let ctx' = replaceStubbedTree ctx+ runCtxActions ctx' $ commandExecute reloadSidebarTreeCommandHandler+ cursorShouldBeOnAfterSearch ctx "/new/" [1, 0]++replaceStubbedTree :: Context -> Context+replaceStubbedTree ctx = ctx{fileContext = newFileContext}+ where+ newFileContext = (fileContext ctx){HFC.contextFileTreeLoader = altFileTreeStub}++altFileTreeStub :: IO (Forest DirectoryTreeElement)+altFileTreeStub = return [+ Node (DirectoryTreeElement "b" "/xxx/b" False) [],+ Node (DirectoryTreeElement "c" "/xxx/c" True) [+ Node (DirectoryTreeElement "new" "/xxx/c/new" False) []+ ]]++getDirectoryListingSidebarRootItems :: Context -> IO [String]+getDirectoryListingSidebarRootItems ctx = do+ let treeView = HC.sidebarTree . uiContext $ ctx+ maybeTreeModel <- treeViewGetModel treeView+ let treeModel = fromJust maybeTreeModel+ maybeRoot <- treeModelGetIter treeModel [0]+ getSiblingItems treeModel maybeRoot++getSiblingItems :: TreeModel -> Maybe TreeIter -> IO [String]+getSiblingItems _ Nothing = return []+getSiblingItems treeModel (Just iter) = do+ let colId = makeColumnIdString 0+ value <- treeModelGetValue treeModel iter colId+ siblings <- getSiblingItems treeModel =<< treeModelIterNext treeModel iter+ return $ value : siblings++
+ test/Hob/Command/ReplaceTextSpec.hs view
@@ -0,0 +1,102 @@+module Hob.Command.ReplaceTextSpec (main, spec) where++import Control.Monad.State (liftIO)+import Data.IORef+import Data.Maybe+import Data.Text (pack)+import Graphics.UI.Gtk+import Test.Hspec++import Hob.Command.ReplaceText+import Hob.Context+import qualified Hob.Context.UiContext as HC+import Hob.Ui.Editor (getActiveEditor, newEditorForText)++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "replace text command matcher" $ do+ it "accepts when command starts with the configured letter" $ do+ let handler _ _ = CommandHandler Nothing (return())+ let matcher = createMatcherForReplace 's' handler+ isJust (matchCommand matcher "s//") `shouldBe` True++ it "does not accept when command starts with another than the configured letter" $ do+ let handler _ _ = CommandHandler Nothing (return())+ let matcher = createMatcherForReplace 's' handler+ isJust (matchCommand matcher "x//") `shouldBe` False++ it "does not accept when command is empty" $ do+ let handler _ _ = CommandHandler Nothing (return())+ let matcher = createMatcherForReplace 's' handler+ isJust (matchCommand matcher "") `shouldBe` False++ it "parses search and replace strings" $ do+ let handler "S" "R" = CommandHandler Nothing (return())+ handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""+ matcher = createMatcherForReplace 'x' handler+ matchResult = matchCommand matcher "x/S/R"+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute (fromJust matchResult)++ it "ignores options when parsing search and replace strings" $ do+ let handler "S" "R" = CommandHandler Nothing (return())+ handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""+ matcher = createMatcherForReplace 'x' handler+ matchResult = matchCommand matcher "x#S#R#options"+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute (fromJust matchResult)++ it "matches escaped separator char as text" $ do+ let handler "S/S" "R/R" = CommandHandler Nothing (return())+ handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""+ matcher = createMatcherForReplace 'x' handler+ matchResult = matchCommand matcher "x/S\\/S/R\\/R"+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute (fromJust matchResult)++ it "matches escaped any char as escape seq and text" $ do+ let handler "S\\xS" "R\\xR" = CommandHandler Nothing (return())+ handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""+ matcher = createMatcherForReplace 'x' handler+ matchResult = matchCommand matcher "x/S\\xS/R\\xR"+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute (fromJust matchResult)++ it "matches escaped end of string as text" $ do+ let handler "S" "R\\" = CommandHandler Nothing (return())+ handler s r = error $ "unexpected invokation with \""++s++ "\" / \""++r++"\""+ matcher = createMatcherForReplace 'x' handler+ matchResult = matchCommand matcher "x/S/R\\"+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute (fromJust matchResult)++ describe "replace text command handler" $ do+ it "focuses editor on execute" $ do+ (ctx, _) <- loadGuiWithEditor+ runCtxActions ctx $ commandExecute (replaceCommandHandler "text" ":)")+ editorFocused <- widgetGetIsFocus . fromJust =<< getActiveEditor ctx+ editorFocused `shouldBe` True++ it "sets replace mode" $ do+ (ctx, _) <- loadGuiWithEditor+ runCtxActions ctx $ commandExecute (replaceCommandHandler "text" ":)")+ ref <- newIORef Nothing+ runCtxActions ctx $ activeModes >>= (liftIO . writeIORef ref)+ modes <- readIORef ref+ (map modeName . fromJust) modes `shouldBe` ["replace"]++loadGuiWithEditor :: IO (Context, TextBuffer)+loadGuiWithEditor = do+ ctx <- loadDefaultContext+ let notebook = HC.mainNotebook . uiContext $ ctx+ runCtxActions ctx $ newEditorForText notebook Nothing $ pack "text - initial text! text"+ mEditor <- getActiveEditor ctx+ let editor = fromJust mEditor+ buffer <- textViewGetBuffer editor+ return (ctx, buffer)
+ test/Hob/Command/SaveCurrentTabSpec.hs view
@@ -0,0 +1,108 @@+module Hob.Command.SaveCurrentTabSpec (main, spec) where++import Data.IORef+import Data.Maybe+import Data.Text (Text, pack)+import Graphics.UI.Gtk++import Hob.Command.NewTab+import Hob.Command.SaveCurrentTab+import Hob.Context+import qualified Hob.Context.FileContext as HFC+import qualified Hob.Context.StyleContext as HSC+import qualified Hob.Context.UiContext as HUC+import Hob.Control+import Hob.Ui++import Test.Hspec++import HobTest.Context.Default+import HobTest.Context.Stubbed+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "save current tab command" $ do+ it "saves the currently active file" $ do+ (mockedWriter, mockReader) <- mockedFileWriter+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext stubbedFileLoader mockedWriter emptyFileTree+ ctx <- launchFileInContext fc sc "/xxx/testName.hs"+ runCtxActions ctx $ saveCurrentEditorTabHandler emptyFileChooser+ savedFile <- mockReader+ savedFile `shouldBe` Just ("/xxx/testName.hs", pack "file contents for /xxx/testName.hs")++ it "skips save when there is no active file" $ do+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext emptyFileLoader failingFileWriter emptyFileTree+ ctx <- loadGui fc sc+ runCtxActions ctx $ saveCurrentEditorTabHandler emptyFileChooser++ it "marks buffer as unmodified on save" $ do+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext stubbedFileLoader blackholeFileWriter emptyFileTree+ ctx <- launchFileInContext fc sc "/xxx/testName.hs"+ flushEvents+ buffer <- textViewGetBuffer . fromJust =<< getActiveEditor ctx+ textBufferSetModified buffer True+ runCtxActions ctx $ saveCurrentEditorTabHandler emptyFileChooser+ stateAfterSave <- textBufferGetModified buffer+ stateAfterSave `shouldBe` False++ it "requests filename for a new file" $ do+ (mockedWriter, mockReader) <- mockedFileWriter+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext emptyFileLoader mockedWriter emptyFileTree+ ctx <- launchNewFileInContextAndSaveAs fc sc "/xxx/fileResponded.hs"+ savedFile <- mockReader+ savedFile `shouldBe` Just ("/xxx/fileResponded.hs", pack "")+ tabText <- getActiveEditorTabText ctx+ tabText `shouldBe` "fileResponded.hs"++ it "updates the tab title from the newly got filepath" $ do+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext emptyFileLoader blackholeFileWriter emptyFileTree+ ctx <- launchNewFileInContextAndSaveAs fc sc "/xxx/fileResponded.hs"+ buffer <- textViewGetBuffer . fromJust =<< getActiveEditor ctx+ textBufferSetModified buffer True+ tabText <- getActiveEditorTabText ctx+ tabText `shouldBe` "fileResponded.hs*"++launchFileInContext :: HFC.FileContext -> HSC.StyleContext -> String -> IO Context+launchFileInContext fileCtx styleCtx filename = do+ ctx <- loadGui fileCtx styleCtx+ launchEditorTab ctx filename+ return ctx++launchNewFileInContextAndSaveAs :: HFC.FileContext -> HSC.StyleContext -> String -> IO Context+launchNewFileInContextAndSaveAs fileCtx styleCtx filename = do+ ctx <- loadGui fileCtx styleCtx+ runCtxActions ctx editNewFile+ runCtxActions ctx $ saveCurrentEditorTabHandler (stubbedFileChooser $ Just filename)+ return ctx++launchEditorTab :: Context -> String -> IO ()+launchEditorTab ctx file = do+ let notebook = HUC.mainNotebook . uiContext $ ctx+ launchNewFileEditor ctx notebook file++getActiveEditorTabText :: Context -> IO String+getActiveEditorTabText ctx = do+ let notebook = HUC.mainNotebook . uiContext $ ctx+ currentlyActiveEditor <- getActiveEditorTab ctx+ text <- notebookGetTabLabelText notebook $ fromJust currentlyActiveEditor+ return $ fromJust text++mockedFileWriter :: IO (HFC.FileWriter, IO (Maybe (String, Text)))+mockedFileWriter = do+ recorder <- newIORef Nothing+ return (curry $ writeIORef recorder . Just, readIORef recorder)++stubbedFileChooser :: Maybe FilePath -> NewFileNameChooser+stubbedFileChooser = return++emptyFileChooser :: NewFileNameChooser+emptyFileChooser = stubbedFileChooser Nothing
+ test/Hob/Context/FileContextSpec.hs view
@@ -0,0 +1,23 @@+module Hob.Context.FileContextSpec (main, spec) where++import Graphics.UI.Gtk.SourceView (sourceLanguageGetName)+import Hob.Context.FileContext+import Test.Hspec++import HobTest.Context.Default++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "sourceLanguage" $+ it "guesses language based on the file ending" $ do+ ctx <- stubbedCtx+ Just lang <- sourceLanguage ctx "/tmp/yyy/test.hs"+ name <- sourceLanguageGetName lang+ name `shouldBe` "Haskell"++stubbedCtx :: IO FileContext+stubbedCtx = defaultFileContext emptyFileLoader blackholeFileWriter emptyFileTree+
+ test/Hob/Context/StyleContextSpec.hs view
@@ -0,0 +1,30 @@+module Hob.Context.StyleContextSpec (main, spec) where++import Graphics.UI.Gtk.SourceView (sourceStyleSchemeGetName)+import Hob.Context.StyleContext+import Test.Hspec++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "uiFile" $+ it "returns prefixed path" $ do+ ctx <- stubbedCtx+ uiFile ctx `shouldBe` "app-data/ui.glade"++ describe "uiTheme" $+ it "returns prefixed path" $ do+ ctx <- stubbedCtx+ uiTheme ctx `shouldBe` "app-data/themes/gtk/default/gtk-dark.css"++ describe "sourceStyleScheme" $+ it "returns source style to use" $ do+ ctx <- stubbedCtx+ Just style <- sourceStyleScheme ctx $ Just "/tmp/yyy/test.hs"+ name <- sourceStyleSchemeGetName style+ name `shouldBe` "Molokai"++stubbedCtx :: IO StyleContext+stubbedCtx = defaultStyleContext "app-data"
+ test/Hob/ContextSpec.hs view
@@ -0,0 +1,276 @@+module Hob.ContextSpec (main, spec) where++import Control.Monad.Reader+import Data.IORef+import Data.Maybe (fromJust, isJust, isNothing)+import Data.Monoid+import Graphics.UI.Gtk (Modifier (..))++import Hob.Context++import Test.Hspec++import HobTest.Context.Default+import HobTest.Control+++dummyEditor :: Editor+dummyEditor = Editor+ { editorId = \_ -> return 1+ , enterEditorMode = \editor mode -> do+ currentModes <- runOnEditor modeStack editor+ return $ editor{modeStack = \_ -> return (currentModes ++ [mode])}+ , exitLastEditorMode = \editor -> do+ currentModes <- runOnEditor modeStack editor+ return $ editor{modeStack = \_ -> return (init currentModes)}+ , modeStack = \_ -> return []+ , isCurrentlyActive = \_ -> return True+ }+++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describe "command matcher" $ do+ describe "mempty" $ do+ it "does not return any commands on matching a command" $+ expectNoCommandHandler $ matchCommand mempty "/asd"++ it "does not return any commands on matching a key binding" $+ expectNoCommandHandler $ matchKeyBinding mempty ([Control], "S")++ it "combines command matchers on mappend with the identity on the left" $ do+ let matcher = matcherForCommand "test"+ let combinedMatcher = mempty `mappend` matcher+ expectCommandHandler $ matchCommand combinedMatcher "test"++ it "combines key binding matchers on mappend with the identity on the left" $ do+ let matcher = matcherForKeyBinding ([Control], "S")+ let combinedMatcher = mempty `mappend` matcher+ expectCommandHandler $ matchKeyBinding combinedMatcher ([Control], "S")++ it "combines command matchers on mappend with the identity on the right" $ do+ let matcher = matcherForCommand "test"+ let combinedMatcher = matcher `mappend` mempty+ expectCommandHandler $ matchCommand combinedMatcher "test"++ it "combines key binding matchers on mappend with the identity on the right" $ do+ let matcher = matcherForKeyBinding ([Control], "S")+ let combinedMatcher = matcher `mappend` mempty+ expectCommandHandler $ matchKeyBinding combinedMatcher ([Control], "S")++ it "combines command matchers assiciatively" $ do+ let matcher1 = matcherForCommand "test1"+ let matcher2 = matcherForCommand "test2"+ let matcher3 = matcherForCommand "test3"+ let combinedMatcher1 = (matcher1 `mappend` matcher2) `mappend` matcher3+ let combinedMatcher2 = matcher1 `mappend` (matcher2 `mappend` matcher3)+ expectCommandHandler $ matchCommand combinedMatcher1 "test1"+ expectCommandHandler $ matchCommand combinedMatcher1 "test2"+ expectCommandHandler $ matchCommand combinedMatcher1 "test3"+ expectCommandHandler $ matchCommand combinedMatcher2 "test1"+ expectCommandHandler $ matchCommand combinedMatcher2 "test2"+ expectCommandHandler $ matchCommand combinedMatcher2 "test3"+ expectNoCommandHandler $ matchCommand combinedMatcher1 "test"+ expectNoCommandHandler $ matchCommand combinedMatcher2 "test"++ describe "command matcher for prefix" $ do+ it "does not match unknown prefix command" $ do+ let matcher = createMatcherForPrefix "/" $ const emptyHandler+ let matchedHandler = matchCommand matcher "%test text"+ isNothing matchedHandler `shouldBe` True++ it "matches known prefix command" $ do+ handledText <- executeMockedMatcher "/" "/test text"+ handledText `shouldBe` Just "test text"++ it "matches known prefix command with no text" $ do+ handledText <- executeMockedMatcher "/" "/"+ handledText `shouldBe` Just ""++ describe "command matcher for key binding" $ do+ it "does not match unknown key binding" $ do+ let matcher = createMatcherForKeyBinding ([Control], "S") emptyHandler+ let matchedHandler = matchKeyBinding matcher ([Control], "X")+ isNothing matchedHandler `shouldBe` True++ it "matches known key binding" $ do+ ctx <- loadDefaultContext+ (handler, readHandledText) <- recordingHandler+ let matcher = createMatcherForKeyBinding ([Control], "S") $ handler "test"+ let matchedHandler = matchKeyBinding matcher ([Control], "S")+ handledText <- executeRecordingHandler ctx matchedHandler readHandledText+ handledText `shouldBe` Just "test"++ describe "command matcher text command" $ do+ it "does not match unknown text command" $ do+ let matcher = createMatcherForCommand "hi" emptyHandler+ let matchedHandler = matchCommand matcher "ho"+ isNothing matchedHandler `shouldBe` True++ it "matches known command" $ do+ ctx <- loadDefaultContext+ (handler, readHandledText) <- recordingHandler+ let matcher = createMatcherForCommand "hi" $ handler "test"+ let matchedHandler = matchCommand matcher "hi"+ handledText <- executeRecordingHandler ctx matchedHandler readHandledText+ handledText `shouldBe` Just "test"++ describe "app runner" $ do+ it "runs empty monad" $ do+ ctx <- loadDefaultContext+ runCtxActions ctx $ return ()++ it "can defer command execution to IO" $ do+ record <- newIORef (0::Int)+ ctx <- loadDefaultContext+ let countingCommand = liftIO $ modifyIORef record (+1)+ let deferCommand cmd = liftIO $ runCtxActions ctx cmd+ deferCommand (countingCommand >>+ deferCommand (countingCommand >>+ deferCommand countingCommand))+ invokeCount <- readIORef record+ invokeCount `shouldBe` (3::Int)++ describe "context commands" $ do+ it "returns Nothing for list of modes if there are no editors" $ do+ ctx <- loadContextWithEditors []+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty $ return()+ modes <- getActiveModes ctx+ isNothing modes `shouldBe` True++ it "enters given mode to the active editor" $ do+ ctx <- loadContextWithEditors [dummyEditor]+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty $ return()+ modes <- getActiveModes ctx+ (modeName . last . fromJust) modes `shouldBe` "testmode"++ it "removes mode from the active editor on exitMode" $ do+ ctx <- loadContextWithEditors [dummyEditor]+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty $ return()+ runCtxActions ctx exitLastMode+ modes <- getActiveModes ctx+ (length . fromJust) modes `shouldBe` 0++ it "emits mode change event on entering a mode" $ do+ record <- newIORef False+ ctx <- loadContextWithEditors [dummyEditor]+ runCtxActions ctx $ registerEventHandler (Event "core.mode.change") (liftIO $ writeIORef record True)+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty $ return()+ invoked <- readIORef record+ invoked `shouldBe` True++ it "emits mode change event on exiting a mode" $ do+ record <- newIORef False+ ctx <- loadContextWithEditors [dummyEditor]+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty $ return()+ runCtxActions ctx $ registerEventHandler (Event "core.mode.change") (liftIO $ writeIORef record True)+ runCtxActions ctx exitLastMode+ invoked <- readIORef record+ invoked `shouldBe` True++ describe "active command matcher retriever" $ do+ it "retains base command matcher" $ do+ ctx <- loadContextWithEditors [dummyEditor]+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty $ return()+ commands <- runApp ctx getActiveCommands+ let cmd = matchKeyBinding commands ([Control], "Tab")+ isJust cmd `shouldBe` True++ it "retrieves active mode command matcher" $ do+ ctx <- loadContextWithEditors [dummyEditor]+ readHandledText <- enterRecordingMode ctx "testMode1" "hi" "test"+ handledText <- executeActiveRecordingHandler ctx "hi" readHandledText+ handledText `shouldBe` Just "test"++ it "retrieves last active mode command first" $ do+ ctx <- loadContextWithEditors [dummyEditor]+ _ <- enterRecordingMode ctx "testMode1" "hi" "test1"+ readHandledText <- enterRecordingMode ctx "testMode2" "hi" "test2"+ handledText <- executeActiveRecordingHandler ctx "hi" readHandledText+ handledText `shouldBe` Just "test2"++ describe "event handler support" $ do+ it "invokes a registered handler on fireEvent" $ do+ record <- newIORef False+ ctx <- loadDefaultContext+ runCtxActions ctx $ registerEventHandler (Event "test.event") (liftIO $ writeIORef record True)+ runCtxActions ctx $ emitEvent (Event "test.event")+ invoked <- readIORef record+ invoked `shouldBe` True++ it "does not invoke an event handler with different name" $ do+ record <- newIORef False+ ctx <- loadDefaultContext+ runCtxActions ctx $ registerEventHandler (Event "test.event1") (liftIO $ writeIORef record True)+ runCtxActions ctx $ emitEvent (Event "test.event2")+ invoked <- readIORef record+ invoked `shouldBe` False++loadContextWithEditors :: [Editor] -> IO Context+loadContextWithEditors newEditors = do+ ctx <- loadDefaultContext+ updateEditors (editors ctx) $ const $ return newEditors+ return ctx++getActiveModes :: Context -> IO (Maybe [Mode])+getActiveModes ctx = do+ record <- newIORef Nothing+ runCtxActions ctx $ activeModes >>= (liftIO . writeIORef record . Just)+ Just modes <- readIORef record+ return modes++executeMockedMatcher :: String -> String -> IO (Maybe String)+executeMockedMatcher prefix text = do+ ctx <- loadDefaultContext+ (handler, readHandledText) <- recordingHandler+ let matcher = createMatcherForPrefix prefix handler+ let matchedHandler = matchCommand matcher text+ runCtxActions ctx $ commandExecute $ fromJust matchedHandler+ readHandledText++expectCommandHandler :: Maybe CommandHandler -> Expectation+expectCommandHandler cmdHandler = isNothing cmdHandler `shouldBe` False++expectNoCommandHandler :: Maybe CommandHandler -> Expectation+expectNoCommandHandler cmdHandler = isNothing cmdHandler `shouldBe` True++matcherForCommand :: String -> CommandMatcher+matcherForCommand command = CommandMatcher (const Nothing) $ emptyCommandHandlerForCommand command+ where emptyCommandHandlerForCommand cmd x = if x == cmd then Just emptyHandler else Nothing++matcherForKeyBinding :: KeyboardBinding -> CommandMatcher+matcherForKeyBinding key = CommandMatcher (emptyCommandHandlerForKey key) (const Nothing)+ where emptyCommandHandlerForKey k x = if x == k then Just emptyHandler else Nothing++emptyHandler :: CommandHandler+emptyHandler = CommandHandler Nothing (return())++recordingHandler :: IO (String -> CommandHandler, IO (Maybe String))+recordingHandler = do+ record <- newIORef Nothing+ return (+ \params -> CommandHandler Nothing (liftIO $ writeIORef record $ Just params),+ readIORef record+ )++executeRecordingHandler :: Context -> Maybe CommandHandler -> IO (Maybe String) -> IO (Maybe String)+executeRecordingHandler ctx handler readHandledText = do+ runCtxActions ctx $ commandExecute $ fromJust handler+ readHandledText++executeActiveRecordingHandler :: Context -> String -> IO (Maybe String) -> IO (Maybe String)+executeActiveRecordingHandler ctx cmd readHandledText = do+ commands <- runApp ctx getActiveCommands+ let command = matchCommand commands cmd+ executeRecordingHandler ctx command readHandledText++enterRecordingMode :: Context -> String -> String -> String -> IO (IO (Maybe String))+enterRecordingMode ctx modename cmd resp = do+ (handler, readHandledText) <- recordingHandler+ let matcher = createMatcherForCommand cmd $ handler resp+ runApp ctx $ enterMode $ Mode modename matcher $ return()+ return readHandledText+
+ test/Hob/ControlSpec.hs view
@@ -0,0 +1,30 @@+module Hob.ControlSpec (main, spec) where++import Data.IORef++import Test.Hspec++import Hob.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "maybeDo" $ do+ it "does not execute on Nothing" $ do+ (executor, mockReader) <- mockedExecutor+ maybeDo executor Nothing+ executionStatus <- mockReader+ executionStatus `shouldBe` Nothing++ it "passes unwrapped value on Just" $ do+ (executor, mockReader) <- mockedExecutor+ maybeDo executor $ Just "test value"+ executionStatus <- mockReader+ executionStatus `shouldBe` Just "test value"++mockedExecutor :: IO (String -> IO(), IO (Maybe String))+mockedExecutor = do+ recorder <- newIORef Nothing+ return (writeIORef recorder . Just, readIORef recorder)
+ test/Hob/DirectoryTreeSpec.hs view
@@ -0,0 +1,72 @@+module Hob.DirectoryTreeSpec (main, spec) where++import Control.Monad.Error+import Data.Tree+import Hob.DirectoryTree+import Test.Hspec++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "fileTreeGenerator" $ do+ it "returns directory contents" $ do+ let dirContentsStub _ = return ["nd1", "nd2"]+ isDirStub _ = return False+ fileTreeGenerator' = fileTreeGenerator dirContentsStub isDirStub+ items <- fileTreeGenerator' "/xxx/"+ items `shouldBe` [Node (DirectoryTreeElement "nd1" "/xxx/nd1" False) [],+ Node (DirectoryTreeElement "nd2" "/xxx/nd2" False) []]++ it "returns sub-directory contents" $ do+ let dirContentsStub "/xxx" = return ["d1"]+ dirContentsStub "/xxx/d1" = return ["nd2"]+ dirContentsStub _ = throwError $ userError "unexpected directory listing"+ isDirStub d = return $ "/xxx/d1" == d+ fileTreeGenerator' = fileTreeGenerator dirContentsStub isDirStub+ items <- fileTreeGenerator' "/xxx"+ items `shouldBe` [Node (DirectoryTreeElement "d1" "/xxx/d1" True) [+ Node (DirectoryTreeElement "nd2" "/xxx/d1/nd2" False) []]]++ it "hides dot (. | ..) directory contents" $ do+ let dirContentsStub "/xxx" = return ["d1", ".", ".."]+ dirContentsStub "/xxx/d1" = return ["nd2", ".", ".."]+ dirContentsStub _ = throwError $ userError "unexpected directory listing"+ isDirStub d = return $ "/xxx/d1" == d+ fileTreeGenerator' = fileTreeGenerator dirContentsStub isDirStub+ items <- fileTreeGenerator' "/xxx"+ items `shouldBe` [Node (DirectoryTreeElement "d1" "/xxx/d1" True) [+ Node (DirectoryTreeElement "nd2" "/xxx/d1/nd2" False) []]]+++ it "hides .git directories" $ do+ let dirContentsStub "/xxx" = return ["d1", ".git"]+ dirContentsStub "/xxx/d1" = return ["nd2"]+ dirContentsStub _ = throwError $ userError "unexpected directory listing"+ isDirStub d = return $ "/xxx/d1" == d+ fileTreeGenerator' = fileTreeGenerator dirContentsStub isDirStub+ items <- fileTreeGenerator' "/xxx"+ items `shouldBe` [Node (DirectoryTreeElement "d1" "/xxx/d1" True) [+ Node (DirectoryTreeElement "nd2" "/xxx/d1/nd2" False) []]]++ it "sorts the directory files" $ do+ let dirContentsStub _ = return ["nd2", "nd1"]+ isDirStub _ = return False+ fileTreeGenerator' = fileTreeGenerator dirContentsStub isDirStub+ items <- fileTreeGenerator' "/xxx/"+ items `shouldBe` [Node (DirectoryTreeElement "nd1" "/xxx/nd1" False) [],+ Node (DirectoryTreeElement "nd2" "/xxx/nd2" False) []]++ it "sorts the directory subdirectories at the top" $ do+ let dirContentsStub "/xxx/" = return ["nd1", "zd2", "zd1"]+ dirContentsStub _ = return []+ isDirStub "/xxx/zd1" = return True+ isDirStub "/xxx/zd2" = return True+ isDirStub _ = return False+ fileTreeGenerator' = fileTreeGenerator dirContentsStub isDirStub+ items <- fileTreeGenerator' "/xxx/"+ items `shouldBe` [Node (DirectoryTreeElement "zd1" "/xxx/zd1" True) [],+ Node (DirectoryTreeElement "zd2" "/xxx/zd2" True) [],+ Node (DirectoryTreeElement "nd1" "/xxx/nd1" False) []]+
+ test/Hob/Ui/CommandEntrySpec.hs view
@@ -0,0 +1,145 @@+module Hob.Ui.CommandEntrySpec (main, spec) where++import Control.Monad.Reader+import Data.IORef+import Graphics.UI.Gtk+import Graphics.UI.Gtk.General.StyleContext++import Hob.Context+import Hob.Context.UiContext+import Hob.Control+import Hob.Ui.CommandEntry++import Test.Hspec++import HobTest.Context.Default+import HobTest.Control++type CommandHandlerReaders = (IO (Maybe String), IO (Maybe String), IO (Maybe String))+type EntryApi = (App(), App())++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "command entry" $ do+ it "is named" $ do+ ctx <- loadDefaultContext+ name <- widgetGetName $ commandEntry . uiContext $ ctx+ name `shouldBe` "commandEntry"++ it "initially there is no error class applied" $ do+ ctx <- loadDefaultContext+ styleCtx <- widgetGetStyleContext $ commandEntry . uiContext $ ctx+ hasErrorClass <- styleContextHasClass styleCtx "error"+ hasErrorClass `shouldBe` False++ it "applies error style class if the command is unknown" $ do+ ctx <- loadDefaultContext+ let entry = commandEntry . uiContext $ ctx+ entrySetText entry "qweqwe"+ styleCtx <- widgetGetStyleContext entry+ flushEvents+ hasErrorClass <- styleContextHasClass styleCtx "error"+ hasErrorClass `shouldBe` True++ it "removes error style on empty command" $ do+ ctx <- loadDefaultContext+ let entry = commandEntry . uiContext $ ctx+ entrySetText entry "not empty"+ styleCtx <- widgetGetStyleContext entry+ styleContextAddClass styleCtx "error"+ entrySetText entry ""+ flushEvents+ hasErrorClass <- styleContextHasClass styleCtx "error"+ hasErrorClass `shouldBe` False++ it "removes error style on known command" $ do+ (ctx, entry, entryApi, _) <- loadDefaultGuiWithMockedCommand+ styleCtx <- widgetGetStyleContext entry+ styleContextAddClass styleCtx "error"+ runCtxActions ctx $ invokePreview entry entryApi "cmd->asd"+ hasErrorClass <- styleContextHasClass styleCtx "error"+ hasErrorClass `shouldBe` False++ it "invokes preview on the command" $ do+ (ctx, entry, entryApi, (_, previewReader, previewResetReader)) <- loadDefaultGuiWithMockedCommand+ runCtxActions ctx $ invokePreview entry entryApi "cmd->asd"+ previewText <- previewReader+ previewResetText <- previewResetReader+ previewText `shouldBe` Just "asd"+ previewResetText `shouldBe` Nothing++ it "resets preview before next preview" $ do+ (ctx, entry, entryApi, (_, previewReader, previewResetReader)) <- loadDefaultGuiWithMockedCommand+ runCtxActions ctx $ invokePreview entry entryApi "cmd->asd"+ runCtxActions ctx $ invokePreview entry entryApi "cmd->as"+ previewText <- previewReader+ previewResetText <- previewResetReader+ previewText `shouldBe` Just "as"+ previewResetText `shouldBe` Just "called"++ it "executes the command" $ do+ (ctx, entry, entryApi, (executeReader, _, _)) <- loadDefaultGuiWithMockedCommand+ runCtxActions ctx $ invokeCommand entry entryApi "cmd->asd"+ executed <- executeReader+ executed `shouldBe` Just "asd"++ it "clears command entry when executing a command" $ do+ (ctx, entry, entryApi, _) <- loadDefaultGuiWithMockedCommand+ runCtxActions ctx $ invokeCommand entry entryApi "cmd->asd"+ text <- entryGetText entry+ text `shouldBe` ""++ it "resets the last preview command before executing a command" $ do+ (ctx, entry, entryApi, (executeReader, _, previewResetReader)) <- loadDefaultGuiWithMockedCommand+ runCtxActions ctx $ invokeCommand entry entryApi "cmd->asd"+ executed <- executeReader+ previewResetText <- previewResetReader+ executed `shouldBe` Just "asd"+ previewResetText `shouldBe` Just "called"++invokePreview :: Entry -> EntryApi -> String -> App ()+invokePreview entry api text = do+ liftIO $ entrySetText entry text+ fst api++invokeCommand :: Entry -> EntryApi -> String -> App ()+invokeCommand entry api text = do+ invokePreview entry api text+ _ <- snd api+ return()++loadDefaultGuiWithMockedCommand :: IO (Context, Entry, EntryApi, CommandHandlerReaders)+loadDefaultGuiWithMockedCommand = do+ defaultCtx <- loadDefaultContext+ (matcher, readHandledCommands) <- mockedMatcher "cmd->"+ let ctx = defaultCtx{baseCommands = matcher}+ entry <- entryNew+ ret <- runApp ctx (newCommandEntryDetached entry)+ return (ctx, entry, ret, readHandledCommands)++mockedMatcher :: String -> IO (CommandMatcher, CommandHandlerReaders)+mockedMatcher prefix = do+ (handler, readHandledCommands) <- recordingHandler+ let matcher = createMatcherForPrefix prefix handler+ return (matcher, readHandledCommands)++recordingHandler :: IO (String -> CommandHandler, CommandHandlerReaders)+recordingHandler = do+ cmd <- newIORef Nothing+ previewCmd <- newIORef Nothing+ previewResetCmd <- newIORef Nothing+ return (+ \params -> CommandHandler+ (Just $ PreviewCommandHandler+ (liftIO $ writeIORef previewCmd $ Just params)+ (liftIO $ writeIORef previewResetCmd $ Just "called"))+ (liftIO $ writeIORef cmd $ Just params),+ (+ readIORef cmd,+ readIORef previewCmd,+ readIORef previewResetCmd+ )+ )
+ test/Hob/Ui/Editor/SearchSpec.hs view
@@ -0,0 +1,237 @@+module Hob.Ui.Editor.SearchSpec (main, spec) where++import Control.Monad (replicateM_)+import Data.Maybe+import Data.Text (pack)+import Graphics.UI.Gtk+import Graphics.UI.Gtk.SourceView (SourceView)+import Test.Hspec++import Hob.Context+import qualified Hob.Context.UiContext as HC+import Hob.Ui.Editor (getActiveEditor, newEditorForText)+import Hob.Ui.Editor.Search++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+ describeSearchPreview loadGuiAndPreviewSearch resetSearchPreview+ describeSearchExecute loadGuiAndExecuteSearch findFirstFromCursor+ describeSearchExecute loadGuiAndInitReplace (\editor text -> startReplace editor text "-")++ describe "search for the next match" $ do+ it "highlights the next match from cursor on execute" $ do+ buffer <- loadEditorAndExecuteAfterSearch findNext+ buffer `shouldHaveSelectionOffsets` (15, 19)++ it "wraps the search from start if there are no matches till the end on execute" $ do+ buffer <- loadEditorAndExecuteAfterSearch $ \editor -> replicateM_ 3 $ findNext editor+ buffer `shouldHaveSelectionOffsets` (0, 4)++ it "scrolls to the current match on execute" $ do+ let commands editor = do+ findFirstFromCursor editor "customised search string"+ findNext editor+ ensureCursorVisibleAfter commands++ describe "search reset command on mode exit" $ do+ it "removes all search tags on cleanup" $ do+ buffer <- loadEditorAndExecuteAfterSearch resetSearch+ tagStates <- checkSearchPreviewTagsAtRanges buffer [(0, 4), (15, 19)]+ tagStates `shouldBe` [(False, False), (False, False)]++ it "stops the next search" $ do+ buffer <- loadEditorAndExecuteAfterSearch $ \editor -> resetSearch editor >> findNext editor+ buffer `shouldHaveSelectionOffsets` (0, 4)++ describe "search for the previous match" $ do+ it "highlights the previous match from cursor on execute" $ do+ buffer <- loadEditorAndExecuteAfterSearch $ \editor -> findNext editor >> findPrevious editor+ buffer `shouldHaveSelectionOffsets` (0, 4)++ it "wraps the search from start if there are no matches till the end on execute" $ do+ buffer <- loadEditorAndExecuteAfterSearch findPrevious+ buffer `shouldHaveSelectionOffsets` (21, 25)++ it "scrolls to the current match on execute" $ do+ let commands editor = do+ findFirstFromCursor editor "customised search string"+ findPrevious editor+ ensureCursorVisibleAfter commands++ describe "replace next" $ do+ it "does not replace if there is no highlighted text" $ do+ (ctx, buffer) <- loadGuiWithEditor+ withActiveEditor ctx replaceNext+ buffer `shouldHaveText` "text - initial text! text"++ it "replaces previously highlighted text" $ do+ (ctx, buffer) <- loadGuiAndInitReplace+ withActiveEditor ctx replaceNext+ buffer `shouldHaveText` "New:TEXT:New - initial text! text"++ it "does not replace if the highlighted text doesnt match the search string" $ do+ (ctx, buffer) <- loadGuiAndInitReplace+ (s, _) <- textBufferGetSelectionBounds buffer+ e <- textBufferGetIterAtOffset buffer 7+ textBufferSelectRange buffer s e+ withActiveEditor ctx replaceNext+ buffer `shouldHaveText` "text - initial text! text"++ it "stops the next search" $ do+ (ctx, buffer) <- loadGuiAndInitReplace+ withActiveEditor ctx $ \editor -> do+ resetReplace editor+ findNext editor+ buffer `shouldHaveSelectionOffsets` (0, 4)++ it "stops the next replace" $ do+ (ctx, buffer) <- loadGuiAndInitReplace+ withActiveEditor ctx $ \editor -> do+ resetReplace editor+ findFirstFromCursor editor "text"+ replaceNext editor+ buffer `shouldHaveText` "text - initial text! text"++describeSearchPreview :: IO (Context, TextBuffer) -> (SourceView -> IO ()) -> Spec+describeSearchPreview initializePreview resetFnc =+ describe "search preview for the first match" $ do+ it "creates search tag on preview" $ do+ (_, buffer) <- initializePreview+ tagTable <- textBufferGetTagTable buffer+ tag <- textTagTableLookup tagTable "search"+ isNothing tag `shouldBe` False++ it "applies search tag for matches on preview" $ do+ (_, buffer) <- initializePreview+ tagStates <- checkSearchPreviewTagsAtRanges buffer [(0, 4), (15, 19)]+ tagStates `shouldBe` [(True, True), (True, True)]++ it "removes all search tags on preview reset" $ do+ (ctx, buffer) <- initializePreview+ withActiveEditor ctx resetFnc+ tagStates <- checkSearchPreviewTagsAtRanges buffer [(0, 4), (15, 19)]+ tagStates `shouldBe` [(False, False), (False, False)]++describeSearchExecute :: IO (Context, TextBuffer) -> (SourceView -> String -> IO ()) -> Spec+describeSearchExecute initializeExecute invokeFirstFnc =+ describe "search execute for the first match" $ do+ it "applies search tag for matches on execute" $ do+ (_, buffer) <- initializeExecute+ tagStates <- checkSearchPreviewTagsAtRanges buffer [(0, 4), (15, 19)]+ tagStates `shouldBe` [(True, True), (True, True)]++ it "highlights the first match on execute" $ do+ (_, buffer) <- initializeExecute+ buffer `shouldHaveSelectionOffsets` (0, 4)++ it "highlights the next match from cursor on execute" $ do+ (ctx, buffer) <- initializeExecute+ withActiveEditor ctx (`invokeFirstFnc` "text")+ buffer `shouldHaveSelectionOffsets` (15, 19)++ it "wraps the search from start if there are no matches till the end on execute" $ do+ (ctx, buffer) <- initializeExecute+ withActiveEditor ctx $ \editor -> replicateM_ 3 $ invokeFirstFnc editor "text"+ buffer `shouldHaveSelectionOffsets` (0, 4)++ it "scrolls to the current match on execute" $+ ensureCursorVisibleAfter $ \editor -> invokeFirstFnc editor "customised search string at the end"++shouldHaveSelectionOffsets :: TextBuffer -> (Int, Int) -> IO ()+shouldHaveSelectionOffsets buffer offsets = do+ (start, end) <- getSelectionOffsets buffer+ (start, end) `shouldBe` offsets++shouldHaveText :: TextBuffer -> String -> IO ()+shouldHaveText buffer text = do+ bufferText <- (buffer `get` textBufferText)::IO String+ bufferText `shouldBe` text++loadEditorAndExecuteAfterSearch :: (SourceView -> IO ()) -> IO TextBuffer+loadEditorAndExecuteAfterSearch actions = do+ (ctx, buffer) <- loadGuiAndExecuteSearch+ withActiveEditor ctx actions+ return buffer+++ensureCursorVisibleAfter :: (SourceView -> IO()) -> IO ()+ensureCursorVisibleAfter commands = do+ ctx <- loadDefaultContext+ let notebook = HC.mainNotebook . uiContext $ ctx+ let editorText = (concat . replicate 1000 $ "text - initial text! \n") ++ "customised search string at the end\n"+ runCtxActions ctx $ newEditorForText notebook Nothing $ pack editorText+ processGtkEvents+ withActiveEditor ctx commands+ processGtkEvents+ withActiveEditor ctx $ \editor -> do+ buffer <- textViewGetBuffer editor+ visible <- textViewGetVisibleRect editor+ caretIter <- textBufferGetIterAtMark buffer =<< textBufferGetInsert buffer+ cursor <- textViewGetIterLocation editor caretIter+ isRectangleInside visible cursor `shouldBe` True++loadGuiAndPreviewSearch :: IO (Context, TextBuffer)+loadGuiAndPreviewSearch = do+ ctx <- loadDefaultContext+ let notebook = HC.mainNotebook . uiContext $ ctx+ runCtxActions ctx $ newEditorForText notebook Nothing $ pack "text - initial text! text"+ Just editor <- getActiveEditor ctx+ highlightSearchPreview editor "text"+ buffer <- textViewGetBuffer editor+ return (ctx, buffer)++loadGuiAndExecuteSearch :: IO (Context, TextBuffer)+loadGuiAndExecuteSearch = loadGuiAndExecute $ \editor -> findFirstFromCursor editor "text"++loadGuiAndInitReplace:: IO (Context, TextBuffer)+loadGuiAndInitReplace = loadGuiAndExecute $ \editor -> startReplace editor "text" "New:TEXT:New"++loadGuiWithEditor :: IO (Context, TextBuffer)+loadGuiWithEditor = loadGuiAndExecute $ const $ return ()++loadGuiAndExecute :: (SourceView -> IO()) -> IO (Context, TextBuffer)+loadGuiAndExecute actions = do+ (ctx, buffer) <- loadGuiAndPreviewSearch+ withActiveEditor ctx resetSearchPreview+ iterBufferStart <- textBufferGetIterAtOffset buffer 0+ textBufferSelectRange buffer iterBufferStart iterBufferStart+ withActiveEditor ctx actions+ return (ctx, buffer)++getSelectionOffsets :: TextBuffer -> IO (Int, Int)+getSelectionOffsets buffer = do+ (iterStart, iterEnd) <- textBufferGetSelectionBounds buffer+ start <- textIterGetOffset iterStart+ end <- textIterGetOffset iterEnd+ return (start, end)++checkSearchPreviewTagsAtRanges :: TextBuffer -> [(Int, Int)] -> IO [(Bool, Bool)]+checkSearchPreviewTagsAtRanges buffer ranges = do+ tagTable <- textBufferGetTagTable buffer+ tag <- textTagTableLookup tagTable "search"+ mapM (checkPair tag) ranges+ where checkPair tag (l, r) = do+ iterL <- textBufferGetIterAtOffset buffer l+ iterR <- textBufferGetIterAtOffset buffer r+ checkL <- textIterBeginsTag iterL tag+ checkR <- textIterEndsTag iterR tag+ return (checkL, checkR)++isRectangleInside :: Rectangle -> Rectangle -> Bool+isRectangleInside (Rectangle ax ay aw ah) (Rectangle bx by bw bh) =+ (ax <= bx) && (ay <= by) && (ax+aw >= bx+bw) && (ay+ah >= by+bh)++processGtkEvents :: IO ()+processGtkEvents = replicateM_ 500 $ mainIterationDo False++withActiveEditor :: Context -> (SourceView -> IO b) -> IO b+withActiveEditor ctx actions = do+ Just editor <- getActiveEditor ctx+ actions editor+
+ test/Hob/Ui/EditorSpec.hs view
@@ -0,0 +1,123 @@+module Hob.Ui.EditorSpec (main, spec) where++import Test.Hspec++import Control.Monad.Reader+import Data.IORef+import Data.Maybe+import Data.Monoid+import Data.Text (pack, unpack)+import Graphics.UI.Gtk+import Graphics.UI.Gtk.SourceView (SourceView, castToSourceBuffer,+ sourceBufferUndo)++import Hob.Context+import qualified Hob.Context.UiContext as HC+import Hob.Ui+import Hob.Ui.Editor++import HobTest.Context.Default+import HobTest.Control++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "editor ui" $ do+ it "does not allow to undo the intial loaded source" $ do+ ctx <- loadDefaultContext+ editor <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ buffer <- textViewGetBuffer editor+ sourceBufferUndo $ castToSourceBuffer buffer+ editorText <- getEditorText editor+ unpack editorText `shouldBe` "initial text"++ it "sets the tab title when opening a file" $ do+ ctx <- loadDefaultContext+ _ <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ tabText <- getActiveEditorTabText ctx+ tabText `shouldBe` "testName.hs"++ it "updates the tab title to reflect if buffer is modified" $ do+ ctx <- launchNewFileAndSetModified+ tabText <- getActiveEditorTabText ctx+ tabText `shouldBe` "testName.hs*"++ it "retrieves active editor" $ do+ ctx <- loadDefaultContext+ editor <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ activeEditor <- getActiveEditor ctx+ fromJust activeEditor == editor `shouldBe` True++ it "registers the new editor in the context on creation" $ do+ ctx <- loadDefaultContext+ _ <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ registeredEditors <- getEditors $ editors ctx+ length registeredEditors `shouldBe` 1++ it "retrieves editor text" $ do+ ctx <- loadDefaultContext+ editor <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ text <- getEditorText editor+ text `shouldBe` pack "initial text"++ it "retrieves active editor text" $ do+ ctx <- loadDefaultContext+ _ <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ text <- getActiveEditorText ctx+ fromJust text `shouldBe` pack "initial text"++ it "retrieves Nothing for active editor text if there is no active editor" $ do+ ctx <- loadDefaultContext+ text <- getActiveEditorText ctx+ text `shouldBe` Nothing++ it "retrieves current editor from notebook" $ do+ ctx <- loadDefaultContext+ editor <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ tab <- getActiveEditorTab ctx+ activeEditor <- getEditorFromNotebookTab $ fromJust tab+ fromJust activeEditor == editor `shouldBe` True++ it "retrieves the set filepath for an editor" $ do+ ctx <- loadDefaultContext+ editor <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ filePath1 <- getEditorFilePath editor+ setEditorFilePath editor $ Just "/tmp/xxx"+ filePath2 <- getEditorFilePath editor+ filePath1 `shouldBe` Just "/xxx/testName.hs"+ filePath2 `shouldBe` Just "/tmp/xxx"+++ it "invokes mode teardown on exitMode" $ do+ record <- newIORef False+ ctx <- loadDefaultContext+ editor <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ widgetGrabFocus editor+ runCtxActions ctx $ enterMode $ Mode "testmode" mempty (liftIO $ writeIORef record True)+ runCtxActions ctx exitLastMode+ cleanupInvoked <- readIORef record+ cleanupInvoked `shouldBe` True++launchNewFileAndSetModified :: IO Context+launchNewFileAndSetModified = do+ ctx <- loadDefaultContext+ _ <- launchEditorTab ctx $ Just "/xxx/testName.hs"+ buffer <- textViewGetBuffer . fromJust =<< getActiveEditor ctx+ textBufferSetModified buffer True+ return ctx++launchEditorTab :: Context -> Maybe FilePath -> IO SourceView+launchEditorTab ctx file = do+ let notebook = HC.mainNotebook . uiContext $ ctx+ runCtxActions ctx $ newEditorForText notebook file $ pack "initial text"+ mEditor <- getActiveEditor ctx+ return $ fromJust mEditor++getActiveEditorTabText :: Context -> IO String+getActiveEditorTabText ctx = do+ let notebook = HC.mainNotebook . uiContext $ ctx+ currentlyActiveEditor <- getActiveEditorTab ctx+ text <- notebookGetTabLabelText notebook $ fromJust currentlyActiveEditor+ return $ fromJust text
+ test/Hob/Ui/SidebarSearchSpec.hs view
@@ -0,0 +1,150 @@+module Hob.Ui.SidebarSearchSpec (main, spec) where++import Data.Tree+import Graphics.UI.Gtk++import qualified Hob.Context as HC+import qualified Hob.Context.FileContext as HFC+import qualified Hob.Context.StyleContext as HSC+import qualified Hob.Context.UiContext as HC+import Hob.DirectoryTree+import Hob.Ui+import Hob.Ui.SidebarSearch++import Test.Hspec++import HobTest.Context.Default+import HobTest.Sidebar++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "sidebar search" $ do+ it "shows the named search box" $ do+ ctx <- sideBarSearchContext+ startSidebarSearch ctx ""+ name <- widgetGetName $ HC.sidebarTreeSearch . HC.uiContext $ ctx+ name `shouldBe` "sidebarSearchEntry"++ it "places the cursor on the first match on the search start" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "greenFile" [1]++ it "finds part even if start can be eaten" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "greenFileZ" [6]++ it "places the cursor on the first nested match on the search start" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]++ it "places the cursor on the first match on the search start even if started from the middle" $ do+ ctx <- sideBarSearchContext+ treeViewSetCursor (HC.sidebarTree . HC.uiContext $ ctx) [1] Nothing+ cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]++ it "places the cursor on the first match again on the search start even if had the same search text before" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]+ treeViewSetCursor (HC.sidebarTree . HC.uiContext $ ctx) [1] Nothing+ cursorShouldBeOnAfterSearch ctx "redFile" [0, 0]++ it "only looks for the leaf nodes" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "red" [0, 0]++ it "uses fuzzy matching on file name" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "r d e" [0, 0]++ it "uses fuzzy matching on path" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "r dD r r d e" [0, 0]++ it "allows path separator while fuzzy matching on path" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "r/red e" [0, 0]++ it "stays on the same path when search is refined" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "r/r d" [0, 0]+ cursorShouldBeOnAfterRefine ctx "r/r d e" [0, 0]++ it "moves to the new match when search is refined" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearch ctx "r/r d" [0, 0]+ cursorShouldBeOnAfterRefine ctx "r/r d e2" [0, 1]++ it "focuses next file match when requested" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearchAndContinue ctx "r d e" [[0, 0], [0, 1]]++ it "focuses next path match when requested" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearchAndContinue ctx "r/r d e" [[0, 0], [0, 1]]++ it "focuses next multi-level path match when requested" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearchAndContinue ctx "/ Dir//r d e" [[3, 0, 0, 0], [4, 1, 0, 0]]++ it "collapses previously matched path after searching in next subtree" $ do+ ctx <- sideBarSearchContext+ startSidebarSearch ctx "/Dir//r d e"+ idx <- HC.runApp ctx initFileTreeIndex+ HC.runApp ctx $ continueSidebarSearch idx+ expanded <- treeViewRowExpanded (HC.sidebarTree . HC.uiContext $ ctx) [3]+ expanded `shouldBe` False++ it "allows case insensitive search" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearchAndContinue ctx "/ DIR//R D E" [[3, 0, 0, 0], [4, 1, 0, 0]]++ it "finds next top-level file" $ do+ ctx <- sideBarSearchContext+ cursorShouldBeOnAfterSearchAndContinue ctx "green file" [[1], [3,0,0,0], [5]]++ it "applies error style class if there are no matches" $ do+ ctx <- sideBarSearchContext+ startSidebarSearch ctx "AAA!!!AAA"+ ctx `sidebarTreeSearchErrorStateShouldBe` True++ it "removes error style on empty search text" $ do+ ctx <- sideBarSearchContext+ startSidebarSearch ctx "AAA!!!AAA"+ entrySetText (HC.sidebarTreeSearch . HC.uiContext $ ctx) ""+ ctx `sidebarTreeSearchErrorStateShouldBe` False++ it "removes error style on a match" $ do+ ctx <- sideBarSearchContext+ startSidebarSearch ctx "AAA!!!AAA"+ entrySetText (HC.sidebarTreeSearch . HC.uiContext $ ctx) "red"+ ctx `sidebarTreeSearchErrorStateShouldBe` False++sideBarSearchFileTreeStub :: IO (Forest DirectoryTreeElement)+sideBarSearchFileTreeStub = return [+ Node (DirectoryTreeElement "redDir" "/xxx/redDir" True) [+ Node (DirectoryTreeElement "redFile1" "/xxx/redDir/redFile1" False) [],+ Node (DirectoryTreeElement "redFile2" "/xxx/redDir/redFile2" False) []],+ Node (DirectoryTreeElement "greenFile" "/xxx/greenFile" False) [],+ Node (DirectoryTreeElement "redFile" "/xxx/redFile" False) [],+ Node (DirectoryTreeElement "greenDir" "/xxx/greenDir" True) [+ Node (DirectoryTreeElement "greenDir" "/xxx/greenDir/greenDir" True) [+ Node (DirectoryTreeElement "greenDir" "/xxx/greenDir/greenDir/greenDir" True) [+ Node (DirectoryTreeElement "redFile" "/xxx/greenDir/greenDir/greenDir/redFile" False) []]]],+ Node (DirectoryTreeElement "blueFolder" "/xxx/blueFolder" True) [+ Node (DirectoryTreeElement "blueFolder" "/xxx/blueFolder/blueFolder" True) [+ Node (DirectoryTreeElement "blueFolder" "/xxx/blueFolder/blueFolder/blueFolder" True) [+ Node (DirectoryTreeElement "redFile" "/xxx/blueFolder/blueFolder/blueFolder/redFile" False) []]],+ Node (DirectoryTreeElement "blueDir" "/xxx/blueFolder/blueDir" True) [+ Node (DirectoryTreeElement "blueDir" "/xxx/blueFolder/blueDir/blueDir" True) [+ Node (DirectoryTreeElement "redFile" "/xxx/blueFolder/blueDir/blueDir/redFile" False) []]]],+ Node (DirectoryTreeElement "greenFile2" "/xxx/greenFile2" False) [],+ Node (DirectoryTreeElement "greegreenFileZ" "/xxx/greegreenFileZ" False) []]++sideBarSearchContext :: IO HC.Context+sideBarSearchContext = do+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext emptyFileLoader blackholeFileWriter sideBarSearchFileTreeStub+ loadGui fc sc
+ test/Hob/Ui/SidebarSpec.hs view
@@ -0,0 +1,61 @@+module Hob.Ui.SidebarSpec (main, spec) where++import Data.Maybe+import Data.Text (unpack)+import Graphics.UI.Gtk++import qualified Hob.Context as HC+import qualified Hob.Context.UiContext as HC+import Hob.Control+import Hob.Ui.Editor++import Test.Hspec++import HobTest.Context.Default+import HobTest.Context.Stubbed++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "sidebar" $ do+ it "is named" $ do+ ctx <- loadDefaultContext+ name <- widgetGetName $ HC.sidebarTree . HC.uiContext $ ctx+ name `shouldBe` "directoryListing"++ it "opens a file editor" $ do+ ctx <- loadStubbedContext+ activateDirectoryPath ctx [2]+ flushEvents+ editorText <- getActiveEditorText ctx+ (unpack . fromJust $ editorText) `shouldBe` "file contents for /xxx/c"++ it "does not open a file editor for directory" $ do+ ctx <- loadStubbedContext+ activateDirectoryPath ctx [0]+ pagesAfterActivatingDirectory <- getNumberOfEditorPages ctx+ pagesAfterActivatingDirectory `shouldBe` 0++ it "expands subtree on directory activation" $ do+ ctx <- loadStubbedContext+ activateDirectoryPath ctx [0]+ expanded <- treeViewRowExpanded (HC.sidebarTree . HC.uiContext $ ctx) [0]+ expanded `shouldBe` True++ it "does not open a file editor for files it cannot read" $ do+ ctx <- loadStubbedContext+ activateDirectoryPath ctx [3]+ pagesAfterActivatingDirectory <- getNumberOfEditorPages ctx+ pagesAfterActivatingDirectory `shouldBe` 0++activateDirectoryPath :: HC.Context -> TreePath -> IO ()+activateDirectoryPath ctx path = do+ let treeView = HC.sidebarTree . HC.uiContext $ ctx+ firstColumn <- treeViewGetColumn treeView 0+ treeViewRowActivated treeView path $ fromJust firstColumn+++getNumberOfEditorPages :: HC.Context -> IO Int+getNumberOfEditorPages = notebookGetNPages . HC.mainNotebook . HC.uiContext
+ test/Hob/UiSpec.hs view
@@ -0,0 +1,21 @@+module Hob.UiSpec (main, spec) where++import Graphics.UI.Gtk++import qualified Hob.Context as HC+import qualified Hob.Context.UiContext as HC++import Test.Hspec++import HobTest.Context.Default++main :: IO ()+main = hspec spec++spec :: Spec+spec =+ describe "mainWindow" $+ it "is named" $ do+ ctx <- loadDefaultContext+ name <- widgetGetName $ HC.mainWindow . HC.uiContext $ ctx+ name `shouldBe` "mainWindow"
+ test/HobTest/Context/Default.hs view
@@ -0,0 +1,32 @@+module HobTest.Context.Default (+ loadDefaultContext,+ emptyFileTree,+ emptyFileLoader,+ blackholeFileWriter+ ) where++import Data.Text (pack)++import qualified Hob.Context as HC+import qualified Hob.Context.FileContext as HFC+import qualified Hob.Context.StyleContext as HSC+import Hob.Control (flushEvents)++import Hob.Ui++blackholeFileWriter :: HFC.FileWriter+blackholeFileWriter _ _ = return ()++emptyFileTree :: HFC.FileTreeLoader+emptyFileTree = return []++emptyFileLoader :: HFC.FileLoader+emptyFileLoader _ = return $ Just $ pack ""++loadDefaultContext :: IO HC.Context+loadDefaultContext = do+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext emptyFileLoader blackholeFileWriter emptyFileTree+ ctx <- loadGui fc sc+ flushEvents+ return ctx
+ test/HobTest/Context/Stubbed.hs view
@@ -0,0 +1,41 @@+module HobTest.Context.Stubbed (+ loadStubbedContext,+ stubbedFileLoader,+ failingFileWriter+ ) where++import Control.Monad.Error (throwError)+import Data.Text (pack)+import Data.Tree++import qualified Hob.Context as HC+import qualified Hob.Context.FileContext as HFC+import qualified Hob.Context.StyleContext as HSC++import Hob.DirectoryTree+import Hob.Ui++fileTreeStub :: IO (Forest DirectoryTreeElement)+fileTreeStub = return [+ Node (DirectoryTreeElement "a" "/xxx/a" True) [+ Node (DirectoryTreeElement "b" "/xxx/a/b" False) []],+ Node (DirectoryTreeElement "a.b" "/xxx/a.b" False) [],+ Node (DirectoryTreeElement "c" "/xxx/c" False) [],+ Node (DirectoryTreeElement "-" "/xxx/cannotRead" False) []]++failingFileWriter :: HFC.FileWriter+failingFileWriter _ _ = throwError $ userError "cannot write files stub"++stubbedFileLoader :: HFC.FileLoader+stubbedFileLoader "/xxx/c" = return $ Just $ pack "file contents for /xxx/c"+stubbedFileLoader "/xxx/a/b" = return $ Just $ pack "file contents for /xxx/a/b"+stubbedFileLoader "/xxx/a.b" = return $ Just $ pack "file contents for /xxx/a.b"+stubbedFileLoader "/xxx/cannotRead" = return Nothing+stubbedFileLoader "/xxx/testName.hs" = return $ Just $ pack "file contents for /xxx/testName.hs"+stubbedFileLoader path = throwError $ userError $ "cannot open unknown file: "++path++loadStubbedContext :: IO HC.Context+loadStubbedContext = do+ sc <- HSC.defaultStyleContext "app-data"+ fc <- HFC.defaultFileContext stubbedFileLoader failingFileWriter fileTreeStub+ loadGui fc sc
+ test/HobTest/Control.hs view
@@ -0,0 +1,11 @@+module HobTest.Control (+ runCtxActions+) where++import Hob.Context+import Hob.Control (flushEvents)++runCtxActions :: Context -> App() -> IO()+runCtxActions ctx actions = do+ deferredRunner ctx actions+ flushEvents
+ test/HobTest/Editor.hs view
@@ -0,0 +1,29 @@+module HobTest.Editor (+ launchNewFile,+ launchEditorTab,+ getNumberOfEditorPages+ ) where++import Graphics.UI.Gtk++import Hob.Command.NewTab+import Hob.Context+import Hob.Context.UiContext++import HobTest.Context.Default+import HobTest.Control++launchNewFile :: IO Context+launchNewFile = do+ ctx <- loadDefaultContext+ runCtxActions ctx $ commandExecute editNewFileCommandHandler+ return ctx++launchEditorTab :: Context -> String -> IO ()+launchEditorTab ctx file = do+ let notebook = mainNotebook . uiContext $ ctx+ launchNewFileEditor ctx notebook file++getNumberOfEditorPages :: Context -> IO Int+getNumberOfEditorPages = notebookGetNPages . mainNotebook . uiContext+
+ test/HobTest/Sidebar.hs view
@@ -0,0 +1,56 @@+module HobTest.Sidebar (+ sidebarTreeSearchErrorStateShouldBe,+ cursorShouldBeOnAfterSearch,+ cursorShouldBeOnAfterRefine,+ cursorShouldBeOnAfterSearchAndContinue,+ cursorShouldBeOn,+ ) where++import Data.Maybe+import Graphics.UI.Gtk+import Graphics.UI.Gtk.General.StyleContext++import qualified Hob.Context as HC+import qualified Hob.Context.UiContext as HC+import Hob.Ui.SidebarSearch++import Test.Hspec+++sidebarTreeSearchErrorStateShouldBe :: HC.Context -> Bool -> IO ()+sidebarTreeSearchErrorStateShouldBe ctx state = do+ styleContext <- widgetGetStyleContext $ HC.sidebarTreeSearch . HC.uiContext $ ctx+ hasErrorClass <- styleContextHasClass styleContext "error"+ hasErrorClass `shouldBe` state++cursorShouldBeOnAfterSearch :: HC.Context -> String -> TreePath -> IO ()+cursorShouldBeOnAfterSearch ctx search expectedPath = do+ startSidebarSearch ctx search+ ctx `cursorShouldBeOn` expectedPath++cursorShouldBeOnAfterRefine :: HC.Context -> String -> TreePath -> IO ()+cursorShouldBeOnAfterRefine ctx search expectedPath = do+ entrySetText (HC.sidebarTreeSearch . HC.uiContext $ ctx) search+ ctx `cursorShouldBeOn` expectedPath++cursorShouldBeOnAfterSearchAndContinue :: HC.Context -> String -> [TreePath] -> IO ()+cursorShouldBeOnAfterSearchAndContinue ctx search expectedPaths = do+ startSidebarSearch ctx search+ ctx `cursorShouldBeOn` head expectedPaths+ mapM_ (\path -> do+ idx <- HC.runApp ctx initFileTreeIndex+ HC.runApp ctx $ continueSidebarSearch idx+ ctx `cursorShouldBeOn` path)+ $ tail expectedPaths+ mapM_ (\path -> do+ idx <- HC.runApp ctx initFileTreeIndex+ HC.runApp ctx $ continueSidebarSearchBackwards idx+ ctx `cursorShouldBeOn` path)+ $ reverse $ init expectedPaths++cursorShouldBeOn :: HC.Context -> TreePath -> IO ()+cursorShouldBeOn ctx expectedPath = do+ let sideBar = HC.sidebarTree . HC.uiContext $ ctx+ (path, column) <- treeViewGetCursor sideBar+ path `shouldBe` expectedPath+ isNothing column `shouldBe` True
+ test/Spec.hs view
@@ -0,0 +1,2 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+