├── .gitignore ├── COPYING ├── Makefile.am ├── README.md ├── TODO ├── autogen.sh ├── configure.ac ├── data ├── Makefile.am └── prefs.ui ├── geany-plugins ├── build │ └── overview.m4 └── overview │ ├── AUTHORS │ ├── COPYING │ ├── ChangeLog │ ├── Makefile.am │ ├── NEWS │ ├── README │ ├── data │ └── Makefile.am │ ├── overview │ └── Makefile.am │ ├── wscript_build │ └── wscript_configure ├── gp-update.sh ├── overview ├── Makefile.am ├── overviewcolor.c ├── overviewcolor.h ├── overviewplugin.c ├── overviewplugin.h ├── overviewprefs.c ├── overviewprefs.h ├── overviewprefspanel.c ├── overviewprefspanel.h ├── overviewscintilla.c ├── overviewscintilla.h ├── overviewui.c └── overviewui.h ├── patches └── geanyscihunting.patch └── screenshots ├── Makefile.am ├── screenshot-dark.png ├── screenshot-keybindings.png ├── screenshot-light.png ├── screenshot-prefs.png └── screenshot-view-menu.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Generic built files 2 | *.[ao] 3 | *.so 4 | *.dll 5 | *.lib 6 | *.dylib 7 | 8 | # Autotools stuff 9 | *.lo 10 | *.la 11 | .deps/ 12 | .libs/ 13 | Makefile 14 | Makefile.in 15 | /aclocal.m4 16 | /ar-lib 17 | /autom4te.cache/ 18 | /build-aux/ 19 | /compile 20 | /config.* 21 | /configure 22 | /depcomp 23 | /install-sh 24 | /libtool 25 | /ltmain.sh 26 | /m4/ 27 | /missing 28 | /stamp-* 29 | 30 | # Project-specific stuff 31 | /index.html 32 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | SUBDIRS = data screenshots overview 3 | dist_doc_DATA = COPYING README.md 4 | 5 | if WITH_MARKDOWN 6 | doc_DATA = index.html 7 | index.html: $(top_srcdir)/README.md 8 | $(AM_V_GEN)$(MARKDOWN) $(top_srcdir)/README.md > $@ 9 | CLEANFILES = index.html 10 | endif 11 | 12 | DISTCHECK_CONFIGURE_FLAGS = --with-geany-libdir='$${libdir}/geany' 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Overview Plugin for Geany 2 | ========================= 3 | 4 | The Overview plugin is a small zoomed-out view next to the normal editor view 5 | that allows to see and navigate a lot of the file at once. It is similar to 6 | the Minimap in SublimeText or such similar feature in numerous other editors. 7 | 8 | Screenshots 9 | ----------- 10 | 11 | This screenshot shows with a light theme, the overview's overlay is inverted, 12 | and the regular scrollbar is not shown. The optional tooltip can be seen 13 | (partially cut-off) in the screenshot also. It shows the line, column and 14 | offset information of the location of the mouse cursor. 15 | 16 | ![Overview plugin screenshot with light theme](screenshots/screenshot-light.png?raw=true) 17 | 18 | This screenshot shows with a dark theme, the overview's overlay is not 19 | inverted, and the regular scrollbar is shown. 20 | 21 | ![Overview plugin screenshot with dark theme](screenshots/screenshot-dark.png?raw=true) 22 | 23 | This screenshot shows the preferences dialog, with the options that can be 24 | configured, saved and restored. Helpful mouse-over tooltips are provided to 25 | give a quick explanation of each preference. 26 | 27 | ![Overview plugin's preferences GUI](screenshots/screenshot-prefs.png?raw=true) 28 | 29 | This screenshot shows the available keybindings which can be configured 30 | through Geany's Preferences dialog from the `Edit->Preferences` menu item. 31 | 32 | ![Keybindings preferences](screenshots/screenshot-keybindings.png?raw=true) 33 | 34 | This screenshot shows how the Overview can be shown/hidden by using Geany's 35 | `View` menu. 36 | 37 | ![Showing and Hiding from the main menu](screenshots/screenshot-view-menu.png?raw=true) 38 | 39 | Building and Installing 40 | ----------------------- 41 | 42 | In order to build the Overview plugin you need: 43 | 44 | - Autotools and a GCC-like C99 compiler (ex. `build-essential` package on Debians) 45 | - GTK+ 2.24 or greater 46 | - Geany, including its development headers, built against GTK+ 2.X 47 | 48 | Once you have all the dependencies, it's just a matter of running the 49 | following commands: 50 | 51 | ```bash 52 | $ ./autogen.sh # note 1 53 | $ ./configure # note 2 54 | $ make 55 | $ make install # note 3 56 | ``` 57 | 58 | **Note 1:** Only run when source was checked-out through Git, not required or 59 | recommended if you're building from a source distribution. 60 | 61 | **Note 2:** Use the `--prefix` option to change installation directories if 62 | desired. If your Geany installation is in an usual place, you'll probably 63 | have to use the `PKG_CONFIG_PATH` environment variable so the build 64 | system finds the correct Geany build flags and paths. 65 | 66 | **Note 3:** May require root permissions, depending on `--prefix` option to 67 | configure, with the default `/usr/local` requiring root permissions on 68 | most systems. 69 | 70 | Using the Plugin 71 | ---------------- 72 | 73 | In order to use the plugin, you need to activate it through Geany's Plugin 74 | Manager dialog, accessible from the `Tools->Plugin Manager` menu item. Once 75 | activated the Overview sidebar view will appear to the right of the main 76 | editor view. 77 | 78 | The configure the plugin, use Geany's Plugin Preferences dialog from the 79 | `Edit->Plugin Preferences`, and select the "Overview" tab. To configure 80 | keybindings for the plugin, for example to show/hide it, use Geany's 81 | Keybindings tab in the Preferences dialog from `Edit->Preferences`. 82 | 83 | You can also hide and show the overview bar by using the `View->Show Overlay` 84 | menu item. If you find you no longer have a need for Geany's regular vertical 85 | editor scrollbar, you can disable it using the Overview preferences. 86 | 87 | Using the plugin is simple. The Overview uses a really simple alogrithm that 88 | seems to work quite well. When you click on the overview, it jumps to the 89 | corresponding location in the main editor view and scrolls it into view. When 90 | you scroll on it, it actually just does the same thing, except it jumps to 91 | each location really quickly as the mouse moves, simulating a scrolling 92 | effect. If the scrolling behaviour feels a little weird at first, this is 93 | probably why. 94 | 95 | Scrolling the main editor view causes the overview to update it's overlay to 96 | show which part of the file is visible in the main editor. 97 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODO: 2 | - handle line-wrapping mode 3 | - configurable cursor for normal and scrolling 4 | - apply `geanyscihunting.patch` to Geany, it's needed to support putting 5 | the overview scintilla on the left. 6 | See: https://github.com/geany/geany/pull/442 7 | - update the overview when the main editor view changes colour schemes 8 | and fonts and such. 9 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir -p m4 build-aux || exit $? 3 | autoreconf -fi 4 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([overview], [1.0], [https://github.com/codebrainz/overview-plugin/issues]) 2 | AC_CONFIG_MACRO_DIR([m4]) 3 | AC_CONFIG_AUX_DIR([build-aux]) 4 | AC_CONFIG_HEADERS([config.h]) 5 | 6 | AM_INIT_AUTOMAKE([1.11.2 -Wall foreign]) 7 | AM_SILENT_RULES([yes]) 8 | AM_PROG_AR 9 | LT_INIT([disable-static]) 10 | 11 | AC_PROG_CC_C99 12 | 13 | PKG_CHECK_MODULES([GEANY], [geany]) 14 | AC_ARG_WITH([geany-libdir], 15 | [AS_HELP_STRING([--with-geany-libdir=DIR], 16 | [Geany's installation libdir [[default=auto]]])], 17 | [geany_libdir=$withval], 18 | [geany_libdir=`$PKG_CONFIG --variable=libdir geany`]) 19 | AC_SUBST([GEANY_PLUGINDIR], [$geany_libdir/geany]) 20 | 21 | AC_PATH_PROG([MARKDOWN], [markdown]) 22 | AM_CONDITIONAL([WITH_MARKDOWN], [test "x$MARKDOWN" != "x"]) 23 | 24 | AC_CONFIG_FILES([ 25 | Makefile 26 | data/Makefile 27 | screenshots/Makefile 28 | overview/Makefile 29 | ]) 30 | AC_OUTPUT 31 | -------------------------------------------------------------------------------- /data/Makefile.am: -------------------------------------------------------------------------------- 1 | dist_pkgdata_DATA = prefs.ui 2 | -------------------------------------------------------------------------------- /data/prefs.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 100 7 | 1 8 | 1 9 | 10 10 | 11 | 12 | 16 13 | 512 14 | 120 15 | 1 16 | 10 17 | 18 | 19 | -10 20 | 20 21 | -10 22 | 1 23 | 10 24 | 25 | 26 | True 27 | False 28 | 12 29 | 5 30 | 2 31 | 4 32 | 2 33 | 34 | 35 | True 36 | False 37 | The amount to zoom the overview sidebar. This should probably negative if you want the sidebar zoomed out. 38 | 0 39 | Zoom Level: 40 | 41 | 42 | 1 43 | 2 44 | GTK_FILL 45 | GTK_FILL 46 | 47 | 48 | 49 | 50 | True 51 | True 52 | The amount to zoom the overview sidebar. This should probably negative if you want the sidebar zoomed out. 53 | 54 | False 55 | False 56 | True 57 | True 58 | overview-zoom-adjustment 59 | 60 | 61 | 1 62 | 2 63 | 1 64 | 2 65 | GTK_FILL 66 | 67 | 68 | 69 | 70 | True 71 | False 72 | The width of the overview sidebar. 73 | 0 74 | Width: 75 | 76 | 77 | GTK_FILL 78 | GTK_FILL 79 | 80 | 81 | 82 | 83 | True 84 | True 85 | The width of the overview sidebar. 86 | 87 | False 88 | False 89 | True 90 | True 91 | overview-width-adjustment 92 | 93 | 94 | 1 95 | 2 96 | GTK_FILL 97 | 98 | 99 | 100 | 101 | True 102 | True 103 | The number of lines to scroll at a time when scrolling the overview sidebar. 104 | 105 | False 106 | False 107 | True 108 | True 109 | overview-scroll-lines-adjustment 110 | 111 | 112 | 1 113 | 2 114 | 2 115 | 3 116 | GTK_FILL 117 | 118 | 119 | 120 | 121 | True 122 | False 123 | The number of lines to scroll at a time when scrolling the overview sidebar. 124 | 0 125 | Scroll Lines: 126 | 127 | 128 | 2 129 | 3 130 | GTK_FILL 131 | GTK_FILL 132 | 133 | 134 | 135 | 136 | True 137 | False 138 | 0 139 | in 140 | 141 | 142 | True 143 | False 144 | 6 145 | 6 146 | 6 147 | 6 148 | 149 | 150 | True 151 | False 152 | 2 153 | 154 | 155 | Position on left 156 | True 157 | True 158 | False 159 | Position the overview bar on the left rather than the right (requires Geany 1.25 or greater). 160 | True 161 | 162 | 163 | True 164 | True 165 | 0 166 | 167 | 168 | 169 | 170 | Hide tooltip 171 | True 172 | True 173 | False 174 | Hide the tooltip that is displayed when mousing over the overview that shows line, column and position information. 175 | True 176 | 177 | 178 | True 179 | True 180 | 1 181 | 182 | 183 | 184 | 185 | Hide editor scrollbar 186 | True 187 | True 188 | False 189 | Whether to hide Geany's regular editor scrollbar while the overview bar is visible. 190 | True 191 | 192 | 193 | True 194 | True 195 | 2 196 | 197 | 198 | 199 | 200 | Disable overlay 201 | True 202 | True 203 | False 204 | Turn off drawing overlay, which shows the region of the main editor view that is currently in view, ontop of the overview bar. 205 | True 206 | 207 | 208 | True 209 | True 210 | 3 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | True 220 | False 221 | Options 222 | True 223 | 224 | 225 | 226 | 227 | 2 228 | 3 229 | 4 230 | GTK_FILL 231 | 232 | 233 | 234 | 235 | True 236 | False 237 | 0 238 | in 239 | 240 | 241 | True 242 | False 243 | 6 244 | 6 245 | 6 246 | 6 247 | 248 | 249 | True 250 | False 251 | 3 252 | 2 253 | 4 254 | 2 255 | 256 | 257 | True 258 | False 259 | The color and opacity of the overlay drawn ontop of the overlay sidebar. 260 | 0 261 | Color: 262 | 263 | 264 | 1 265 | 2 266 | GTK_FILL 267 | GTK_FILL 268 | 269 | 270 | 271 | 272 | True 273 | False 274 | The color and opacity of the border drawn around the revealed area in the overview sidebar. Set to the same as Overlay Color to disable. 275 | 0 276 | Outline Color: 277 | 278 | 279 | 2 280 | 3 281 | GTK_FILL 282 | GTK_FILL 283 | 284 | 285 | 286 | 287 | True 288 | True 289 | True 290 | The color and opacity of the border drawn around the revealed area in the overview sidebar. Set to the same as Overlay Color to disable. 291 | True 292 | #000000000000 293 | 294 | 295 | 1 296 | 2 297 | 2 298 | 3 299 | GTK_FILL 300 | 301 | 302 | 303 | 304 | True 305 | True 306 | True 307 | The color and opacity of the overlay drawn ontop of the overlay sidebar. 308 | True 309 | #000000000000 310 | 311 | 312 | 1 313 | 2 314 | 1 315 | 2 316 | GTK_FILL 317 | 318 | 319 | 320 | 321 | Draw over visible area 322 | True 323 | True 324 | False 325 | When checked it will draw the overlay ontop of the area that is visible in the main editor view, when unchecked, it will do the opposite and draw the overlay everywhere but the visible area, "revealing" the visible part. 326 | True 327 | True 328 | 329 | 330 | 2 331 | GTK_FILL 332 | GTK_FILL 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | True 342 | False 343 | Overlay 344 | True 345 | 346 | 347 | 348 | 349 | 2 350 | 4 351 | 5 352 | GTK_FILL 353 | 354 | 355 | 356 | 357 | -------------------------------------------------------------------------------- /geany-plugins/build/overview.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([GP_CHECK_OVERVIEW], 2 | [ 3 | GP_ARG_DISABLE([overview], [auto]) 4 | 5 | GP_COMMIT_PLUGIN_STATUS([Overview]) 6 | 7 | AC_CONFIG_FILES([ 8 | overview/Makefile 9 | overview/data/Makefile 10 | overview/overview/Makefile 11 | ]) 12 | ]) 13 | -------------------------------------------------------------------------------- /geany-plugins/overview/AUTHORS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/geany-plugins/overview/AUTHORS -------------------------------------------------------------------------------- /geany-plugins/overview/COPYING: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/geany-plugins/overview/COPYING -------------------------------------------------------------------------------- /geany-plugins/overview/ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/geany-plugins/overview/ChangeLog -------------------------------------------------------------------------------- /geany-plugins/overview/Makefile.am: -------------------------------------------------------------------------------- 1 | include $(top_srcdir)/build/vars.auxfiles.mk 2 | SUBDIRS = overview data 3 | plugin = overview 4 | -------------------------------------------------------------------------------- /geany-plugins/overview/NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/geany-plugins/overview/NEWS -------------------------------------------------------------------------------- /geany-plugins/overview/README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/geany-plugins/overview/README -------------------------------------------------------------------------------- /geany-plugins/overview/data/Makefile.am: -------------------------------------------------------------------------------- 1 | overviewdatadir = $(pkgdatadir)/overview 2 | dist_overviewdata_DATA = prefs.ui 3 | -------------------------------------------------------------------------------- /geany-plugins/overview/overview/Makefile.am: -------------------------------------------------------------------------------- 1 | include $(top_srcdir)/build/vars.build.mk 2 | 3 | plugin = overview 4 | 5 | geanyplugins_LTLIBRARIES = overview.la 6 | 7 | overview_la_SOURCES = \ 8 | overviewcolor.c \ 9 | overviewcolor.h \ 10 | overviewplugin.c \ 11 | overviewplugin.h \ 12 | overviewprefs.c \ 13 | overviewprefs.h \ 14 | overviewprefspanel.c \ 15 | overviewprefspanel.h \ 16 | overviewscintilla.c \ 17 | overviewscintilla.h \ 18 | overviewui.c \ 19 | overviewui.h 20 | 21 | overview_la_CFLAGS = \ 22 | $(AM_CFLAGS) \ 23 | -I$(srcdir)/.. \ 24 | -DOVERVIEW_PREFS_UI_FILE=\""$(pkgdatadir)/overview/prefs.ui"\" 25 | 26 | overview_la_LIBADD = \ 27 | $(COMMONLIBS) 28 | 29 | include $(top_srcdir)/build/cppcheck.mk 30 | -------------------------------------------------------------------------------- /geany-plugins/overview/wscript_build: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # WAF build script for geany-plugins - Overview 4 | # 5 | # Copyright 2015 Matthew Brush 6 | # 7 | # This program is free software; you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation; either version 2 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | # 21 | 22 | from build.wafutils import build_plugin 23 | from waflib.Utils import subst_vars 24 | 25 | name = 'Overview' 26 | sources = [ 27 | 'overview/overviewcolor.c', 28 | 'overview/overviewplugin.c', 29 | 'overview/overviewprefs.c', 30 | 'overview/overviewprefspanel.c', 31 | 'overview/overviewscintilla.c', 32 | 'overview/overviewui.c', 33 | ] 34 | includes = ['overview'] 35 | libraries = [ 'C99', 'GTK', 'GLIB', 'GEANY' ] 36 | defines = [ subst_vars('OVERVIEW_PREFS_UI_FILE="${PKGDATADIR}/overview/prefs.ui"', bld.env) ] 37 | 38 | build_plugin(bld, name, 39 | sources=sources, 40 | includes=includes, 41 | libraries=libraries, 42 | defines=defines) 43 | 44 | # install UI file 45 | prefix = '${G_PREFIX}/' if target_is_win32(bld) else '' 46 | datadir = '${GEANYPLUGINS_DATADIR}/geany-plugins/%s' % (name.lower()) 47 | bld.install_files('%s%s' % (prefix, datadir), 'data/prefs.ui') 48 | -------------------------------------------------------------------------------- /geany-plugins/overview/wscript_configure: -------------------------------------------------------------------------------- 1 | from build.wafutils import check_c99 2 | 3 | check_c99(conf) 4 | -------------------------------------------------------------------------------- /gp-update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Run this script from root source directory and provide path to Geany-Plugins 4 | # root source tree as the only argument. 5 | # 6 | 7 | SRCDIR=`pwd` 8 | DSTDIR=$1 9 | 10 | cp -rv $SRCDIR/geany-plugins/* "$DSTDIR" 11 | cp -v $SRCDIR/overview/*.[ch] "$DSTDIR/overview/overview/" || exit $? 12 | cp -v $SRCDIR/data/prefs.ui "$DSTDIR/overview/data/" || exit $? 13 | -------------------------------------------------------------------------------- /overview/Makefile.am: -------------------------------------------------------------------------------- 1 | plugindir = $(GEANY_PLUGINDIR) 2 | plugin_LTLIBRARIES = overview.la 3 | 4 | AM_CFLAGS = \ 5 | $(GEANY_CFLAGS) \ 6 | -I$(top_srcdir) \ 7 | -DOVERVIEW_PREFS_UI_FILE=\""$(pkgdatadir)/prefs.ui"\" 8 | 9 | overview_la_SOURCES = \ 10 | overviewcolor.c \ 11 | overviewcolor.h \ 12 | overviewplugin.c \ 13 | overviewplugin.h \ 14 | overviewprefs.c \ 15 | overviewprefs.h \ 16 | overviewprefspanel.c \ 17 | overviewprefspanel.h \ 18 | overviewscintilla.c \ 19 | overviewscintilla.h \ 20 | overviewui.c \ 21 | overviewui.h 22 | 23 | overview_la_LDFLAGS = -module -avoid-version 24 | overview_la_LIBADD = $(GEANY_LIBS) 25 | -------------------------------------------------------------------------------- /overview/overviewcolor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewcolor.c - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | # include "config.h" 25 | #endif 26 | 27 | #include "overviewcolor.h" 28 | #include 29 | 30 | OverviewColor * 31 | overview_color_copy (OverviewColor *color) 32 | { 33 | OverviewColor *new_color = g_slice_new0 (OverviewColor); 34 | memcpy (new_color, color, sizeof (OverviewColor)); 35 | return new_color; 36 | } 37 | 38 | void 39 | overview_color_free (OverviewColor *color) 40 | { 41 | if (color != NULL) 42 | g_slice_free (OverviewColor, color); 43 | } 44 | 45 | gboolean 46 | overview_color_equal (const OverviewColor *color1, 47 | const OverviewColor *color2) 48 | { 49 | return (color1->red == color2->red && 50 | color1->green == color2->green && 51 | color1->blue == color2->blue && 52 | color1->alpha == color2->alpha); 53 | } 54 | 55 | gboolean 56 | overview_color_parse (OverviewColor *color, 57 | const gchar *color_str) 58 | { 59 | g_return_val_if_fail (color != NULL, FALSE); 60 | g_return_val_if_fail (color_str != NULL, FALSE); 61 | 62 | #if GTK_CHECK_VERSION (3, 0, 0) 63 | GdkRGBA gcolor; 64 | if (gdk_rgba_parse (&gcolor, color_str)) 65 | { 66 | overview_color_from_rgba (color, &gcolor); 67 | return TRUE; 68 | } 69 | #else 70 | GdkColor gcolor; 71 | if (gdk_color_parse (color_str, &gcolor)) 72 | { 73 | overview_color_from_gdk_color (color, &gcolor, 1.0); 74 | return TRUE; 75 | } 76 | #endif 77 | 78 | return FALSE; 79 | } 80 | 81 | gchar * 82 | overview_color_to_string (const OverviewColor *color) 83 | { 84 | g_return_val_if_fail (color != NULL, NULL); 85 | 86 | #if GTK_CHECK_VERSION (3, 0, 0) 87 | GdkRGBA gcolor; 88 | overview_color_to_rgba (color, &gcolor); 89 | return gdk_rgba_to_string (&gcolor); 90 | #else 91 | GdkColor gcolor; 92 | overview_color_to_gdk_color (color, &gcolor); 93 | return gdk_color_to_string (&gcolor); 94 | #endif 95 | } 96 | 97 | void 98 | overview_color_from_gdk_color (OverviewColor *color, 99 | const GdkColor *gcolor, 100 | gdouble alpha) 101 | { 102 | g_return_if_fail (color != NULL); 103 | g_return_if_fail (gcolor != NULL); 104 | 105 | color->red = (gdouble) gcolor->red / G_MAXUINT16; 106 | color->green = (gdouble) gcolor->green / G_MAXUINT16; 107 | color->blue = (gdouble) gcolor->blue / G_MAXUINT16; 108 | color->alpha = alpha; 109 | } 110 | 111 | void 112 | overview_color_to_gdk_color (const OverviewColor *color, 113 | GdkColor *gcolor) 114 | { 115 | g_return_if_fail (color != NULL); 116 | g_return_if_fail (gcolor != NULL); 117 | 118 | gcolor->red = (guint16)(color->red * G_MAXUINT16); 119 | gcolor->green = (guint16)(color->green * G_MAXUINT16); 120 | gcolor->blue = (guint16)(color->blue * G_MAXUINT16); 121 | } 122 | 123 | #if GTK_CHECK_VERSION (3, 0, 0) 124 | void 125 | overview_color_from_rgba (OverviewColor *color, 126 | const GdkRGBA *rgba) 127 | { 128 | g_return_if_fail (color != NULL); 129 | g_return_if_fail (rgba != NULL); 130 | 131 | color->red = rgba->red; 132 | color->green = rgba->green; 133 | color->blue = rgba->blue; 134 | color->alpha = rgba->alpha; 135 | } 136 | 137 | void 138 | overview_color_to_rgba (const OverviewColor *color, 139 | GdkRGBA *rgba) 140 | { 141 | g_return_if_fail (color != NULL); 142 | g_return_if_fail (rgba != NULL); 143 | 144 | rgba->red = color->red; 145 | rgba->green = color->green; 146 | rgba->blue = color->blue; 147 | rgba->alpha = color->alpha; 148 | } 149 | #endif 150 | 151 | void 152 | overview_color_from_int (OverviewColor *color, 153 | guint32 abgr, 154 | gboolean with_alpha) 155 | { 156 | g_return_if_fail (color != NULL); 157 | guint8 r = abgr & 0xFF; 158 | guint8 g = (abgr>>8) & 0xFF; 159 | guint8 b = (abgr>>16) & 0xFF; 160 | guint8 a = 255; 161 | 162 | if (with_alpha) 163 | a = (abgr>>24) & 0xFF; 164 | 165 | color->red = (gdouble)r / G_MAXUINT8; 166 | color->green = (gdouble)g / G_MAXUINT8; 167 | color->blue = (gdouble)b / G_MAXUINT8; 168 | color->alpha = (gdouble)a / G_MAXUINT8; 169 | } 170 | 171 | guint32 172 | overview_color_to_int (const OverviewColor *color, 173 | gboolean with_alpha) 174 | { 175 | g_return_val_if_fail (color != NULL, 0); 176 | 177 | guint32 r = (guint8)(color->red * 255.0); 178 | guint32 g = (guint8)(color->green * 255.0); 179 | guint32 b = (guint8)(color->blue * 255.0); 180 | guint32 a = 0; 181 | 182 | if (with_alpha) 183 | a = (guint8)(color->alpha * 255.0); 184 | 185 | return (a<<24) | (b<<16) | (g<<8) | r; 186 | } 187 | 188 | gboolean 189 | overview_color_from_keyfile (OverviewColor *color, 190 | GKeyFile *keyfile, 191 | const gchar *section, 192 | const gchar *option, 193 | GError **error) 194 | { 195 | gchar *color_key; 196 | gchar *alpha_key; 197 | gchar *clr_str; 198 | gdouble alpha; 199 | 200 | g_return_val_if_fail (color != NULL, FALSE); 201 | g_return_val_if_fail (keyfile != NULL, FALSE); 202 | g_return_val_if_fail (section != NULL, FALSE); 203 | g_return_val_if_fail (option != NULL, FALSE); 204 | 205 | color_key = g_strdup_printf ("%s-color", option); 206 | alpha_key = g_strdup_printf ("%s-alpha", option); 207 | 208 | clr_str = g_key_file_get_string (keyfile, section, color_key, error); 209 | if (*error != NULL) 210 | { 211 | g_free (color_key); 212 | g_free (alpha_key); 213 | return FALSE; 214 | } 215 | 216 | g_free (color_key); 217 | 218 | alpha = g_key_file_get_double (keyfile, section, alpha_key, error); 219 | if (*error != NULL) 220 | { 221 | g_free (alpha_key); 222 | g_free (clr_str); 223 | return FALSE; 224 | } 225 | 226 | g_free (alpha_key); 227 | 228 | if (alpha < 0.0 || alpha > 1.0) 229 | g_warning ("alpha value '%g' from keyfile out of 0-1 range", alpha); 230 | 231 | overview_color_parse (color, clr_str); 232 | color->alpha = alpha; 233 | 234 | g_free (clr_str); 235 | 236 | return TRUE; 237 | } 238 | 239 | gboolean 240 | overview_color_to_keyfile (const OverviewColor *color, 241 | GKeyFile *keyfile, 242 | const gchar *section, 243 | const gchar *option) 244 | { 245 | gchar *color_key; 246 | gchar *alpha_key; 247 | gchar *clr_str; 248 | 249 | g_return_val_if_fail (color != NULL, FALSE); 250 | g_return_val_if_fail (keyfile != NULL, FALSE); 251 | g_return_val_if_fail (section != NULL, FALSE); 252 | g_return_val_if_fail (option != NULL, FALSE); 253 | 254 | color_key = g_strdup_printf ("%s-color", option); 255 | alpha_key = g_strdup_printf ("%s-alpha", option); 256 | 257 | clr_str = overview_color_to_string (color); 258 | g_key_file_set_string (keyfile, section, color_key, clr_str); 259 | g_free (color_key); 260 | g_free (clr_str); 261 | 262 | g_key_file_set_double (keyfile, section, alpha_key, color->alpha); 263 | g_free (alpha_key); 264 | 265 | return TRUE; 266 | } 267 | 268 | void 269 | overview_color_from_color_button (OverviewColor *color, 270 | GtkColorButton *button) 271 | { 272 | GdkColor gcolor; 273 | guint16 alpha; 274 | gdouble falpha; 275 | gtk_color_button_get_color (button, &gcolor); 276 | alpha = gtk_color_button_get_alpha (button); 277 | falpha = (gdouble) alpha / (gdouble) G_MAXUINT16; 278 | overview_color_from_gdk_color (color, &gcolor, falpha); 279 | } 280 | 281 | void 282 | overview_color_to_color_button (const OverviewColor *color, 283 | GtkColorButton *button) 284 | { 285 | GdkColor gcolor; 286 | guint16 alpha; 287 | overview_color_to_gdk_color (color, &gcolor); 288 | gtk_color_button_set_color (button, &gcolor); 289 | alpha = (guint16)(color->alpha * (gdouble) G_MAXUINT16); 290 | gtk_color_button_set_alpha (button, alpha); 291 | } 292 | 293 | GType 294 | overview_color_get_type (void) 295 | { 296 | static GType type = 0; 297 | if (type == 0) 298 | { 299 | type = 300 | g_boxed_type_register_static ("OverviewColor", 301 | (GBoxedCopyFunc) overview_color_copy, 302 | (GBoxedFreeFunc) overview_color_free); 303 | } 304 | return type; 305 | } 306 | -------------------------------------------------------------------------------- /overview/overviewcolor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewcolor.h - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef OVERVIEW_COLOR_H_ 24 | #define OVERVIEW_COLOR_H_ 25 | 26 | #include 27 | 28 | #define OVERVIEW_TYPE_COLOR (overview_color_get_type ()) 29 | #define OVERVIEW_COLOR_INIT { 0.0, 0.0, 0.0, 1.0 } 30 | 31 | typedef struct 32 | { 33 | gdouble red; 34 | gdouble green; 35 | gdouble blue; 36 | gdouble alpha; 37 | } 38 | OverviewColor; 39 | 40 | GType overview_color_get_type (void); 41 | OverviewColor *overview_color_copy (OverviewColor *color); 42 | void overview_color_free (OverviewColor *color); 43 | gboolean overview_color_equal (const OverviewColor *color1, 44 | const OverviewColor *color2); 45 | gboolean overview_color_parse (OverviewColor *color, 46 | const gchar *color_str); 47 | gchar *overview_color_to_string (const OverviewColor *color); 48 | void overview_color_from_gdk_color (OverviewColor *color, 49 | const GdkColor *gcolor, 50 | gdouble alpha); 51 | void overview_color_to_gdk_color (const OverviewColor *color, 52 | GdkColor *gcolor); 53 | #if GTK_CHECK_VERSION (3, 0, 0) 54 | void overview_color_from_rgba (OverviewColor *color, 55 | const GdkRGBA *rgba); 56 | void overview_color_to_rgba (const OverviewColor *color, 57 | GdkRGBA *rgba); 58 | #endif 59 | void overview_color_from_int (OverviewColor *color, 60 | guint32 abgr, 61 | gboolean with_alpha); 62 | guint32 overview_color_to_int (const OverviewColor *color, 63 | gboolean with_alpha); 64 | gboolean overview_color_from_keyfile (OverviewColor *color, 65 | GKeyFile *keyfile, 66 | const gchar *section, 67 | const gchar *option, 68 | GError **error); 69 | gboolean overview_color_to_keyfile (const OverviewColor *color, 70 | GKeyFile *keyfile, 71 | const gchar *section, 72 | const gchar *option); 73 | 74 | void overview_color_from_color_button (OverviewColor *color, 75 | GtkColorButton *button); 76 | void overview_color_to_color_button (const OverviewColor *color, 77 | GtkColorButton *button); 78 | 79 | #endif /* OVERVIEW_COLOR_H_ */ 80 | -------------------------------------------------------------------------------- /overview/overviewplugin.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewplugin.c - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | # include "config.h" 25 | #endif 26 | 27 | #include "overviewplugin.h" 28 | #include "overviewscintilla.h" 29 | #include "overviewprefs.h" 30 | #include "overviewprefspanel.h" 31 | #include "overviewui.h" 32 | #include 33 | 34 | GeanyPlugin *geany_plugin; 35 | GeanyData *geany_data; 36 | GeanyFunctions *geany_functions; 37 | 38 | /* scintilla_get_type() is needed but was only added to the API in 224, but 39 | * previous versions will still work on Linux since it's before the symbol 40 | * linkage was fixed up. TODO: remove this after next Geany release. */ 41 | #if GEANY_API_VERSION >= 224 42 | PLUGIN_VERSION_CHECK (224) 43 | #else 44 | PLUGIN_VERSION_CHECK (211) 45 | #endif 46 | 47 | PLUGIN_SET_INFO ( 48 | "Overview", 49 | _("Provides an overview of the active document"), 50 | "0.01", 51 | "Matthew Brush ") 52 | 53 | static OverviewPrefs *overview_prefs = NULL; 54 | 55 | static void write_config (void); 56 | 57 | static void 58 | on_visible_pref_notify (OverviewPrefs *prefs, 59 | GParamSpec *pspec, 60 | gpointer user_data) 61 | { 62 | write_config (); 63 | } 64 | 65 | static void 66 | toggle_visibility (void) 67 | { 68 | gboolean visible = TRUE; 69 | g_object_get (overview_prefs, "visible", &visible, NULL); 70 | g_object_set (overview_prefs, "visible", !visible, NULL); 71 | } 72 | 73 | enum 74 | { 75 | KB_TOGGLE_VISIBLE, 76 | KB_TOGGLE_POSITION, 77 | KB_TOGGLE_INVERTED, 78 | NUM_KB 79 | }; 80 | 81 | static gboolean 82 | on_kb_activate (guint keybinding_id) 83 | { 84 | switch (keybinding_id) 85 | { 86 | case KB_TOGGLE_VISIBLE: 87 | toggle_visibility (); 88 | break; 89 | case KB_TOGGLE_POSITION: 90 | { 91 | GtkPositionType pos; 92 | g_object_get (overview_prefs, "position", &pos, NULL); 93 | pos = (pos == GTK_POS_LEFT) ? GTK_POS_RIGHT : GTK_POS_LEFT; 94 | g_object_set (overview_prefs, "position", pos, NULL); 95 | break; 96 | } 97 | case KB_TOGGLE_INVERTED: 98 | { 99 | gboolean inv = FALSE; 100 | g_object_get (overview_prefs, "overlay-inverted", &inv, NULL); 101 | g_object_set (overview_prefs, "overlay-inverted", !inv, NULL); 102 | break; 103 | } 104 | default: 105 | break; 106 | } 107 | return TRUE; 108 | } 109 | 110 | static gchar * 111 | get_config_file (void) 112 | { 113 | gchar *dir; 114 | gchar *fn; 115 | static const gchar *def_config = OVERVIEW_PREFS_DEFAULT_CONFIG; 116 | 117 | dir = g_build_filename (geany_data->app->configdir, "plugins", "overview", NULL); 118 | fn = g_build_filename (dir, "prefs.conf", NULL); 119 | 120 | if (! g_file_test (fn, G_FILE_TEST_IS_DIR)) 121 | { 122 | if (g_mkdir_with_parents (dir, 0755) != 0) 123 | { 124 | g_critical ("failed to create config dir '%s': %s", dir, g_strerror (errno)); 125 | g_free (dir); 126 | g_free (fn); 127 | return NULL; 128 | } 129 | } 130 | 131 | g_free (dir); 132 | 133 | if (! g_file_test (fn, G_FILE_TEST_EXISTS)) 134 | { 135 | GError *error = NULL; 136 | if (!g_file_set_contents (fn, def_config, -1, &error)) 137 | { 138 | g_critical ("failed to save default config to file '%s': %s", 139 | fn, error->message); 140 | g_error_free (error); 141 | g_free (fn); 142 | return NULL; 143 | } 144 | } 145 | 146 | return fn; 147 | } 148 | 149 | static void 150 | write_config (void) 151 | { 152 | gchar *conf_file; 153 | GError *error = NULL; 154 | conf_file = get_config_file (); 155 | if (! overview_prefs_save (overview_prefs, conf_file, &error)) 156 | { 157 | g_critical ("failed to save preferences to file '%s': %s", conf_file, error->message); 158 | g_error_free (error); 159 | } 160 | g_free (conf_file); 161 | } 162 | 163 | void 164 | plugin_init (G_GNUC_UNUSED GeanyData *data) 165 | { 166 | gchar *conf_file; 167 | GError *error = NULL; 168 | GeanyKeyGroup *key_group; 169 | 170 | plugin_module_make_resident (geany_plugin); 171 | 172 | overview_prefs = overview_prefs_new (); 173 | conf_file = get_config_file (); 174 | if (! overview_prefs_load (overview_prefs, conf_file, &error)) 175 | { 176 | g_critical ("failed to load preferences file '%s': %s", conf_file, error->message); 177 | g_error_free (error); 178 | } 179 | g_free (conf_file); 180 | 181 | overview_ui_init (overview_prefs); 182 | 183 | key_group = plugin_set_key_group (geany_plugin, 184 | "overview", 185 | NUM_KB, 186 | on_kb_activate); 187 | 188 | keybindings_set_item (key_group, 189 | KB_TOGGLE_VISIBLE, 190 | NULL, 0, 0, 191 | "toggle-visibility", 192 | _("Toggle Visibility"), 193 | overview_ui_get_menu_item ()); 194 | 195 | keybindings_set_item (key_group, 196 | KB_TOGGLE_POSITION, 197 | NULL, 0, 0, 198 | "toggle-position", 199 | _("Toggle Left/Right Position"), 200 | NULL); 201 | 202 | keybindings_set_item (key_group, 203 | KB_TOGGLE_INVERTED, 204 | NULL, 0, 0, 205 | "toggle-inverted", 206 | _("Toggle Overlay Inversion"), 207 | NULL); 208 | 209 | g_signal_connect (overview_prefs, "notify::visible", G_CALLBACK (on_visible_pref_notify), NULL); 210 | } 211 | 212 | void 213 | plugin_cleanup (void) 214 | { 215 | write_config (); 216 | overview_ui_deinit (); 217 | 218 | if (OVERVIEW_IS_PREFS (overview_prefs)) 219 | g_object_unref (overview_prefs); 220 | overview_prefs = NULL; 221 | } 222 | 223 | static void 224 | on_prefs_stored (OverviewPrefsPanel *panel, 225 | OverviewPrefs *prefs, 226 | gpointer user_data) 227 | { 228 | write_config (); 229 | overview_ui_queue_update (); 230 | } 231 | 232 | GtkWidget * 233 | plugin_configure (GtkDialog *dialog) 234 | { 235 | GtkWidget *panel; 236 | panel = overview_prefs_panel_new (overview_prefs, dialog); 237 | g_signal_connect (panel, "prefs-stored", G_CALLBACK (on_prefs_stored), NULL); 238 | return panel; 239 | } 240 | -------------------------------------------------------------------------------- /overview/overviewplugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewplugin.h - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef OVERVIEW_PLUGIN_H 24 | #define OVERVIEW_PLUGIN_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | extern GeanyData *geany_data; 31 | extern GeanyPlugin *geany_plugin; 32 | extern GeanyFunctions *geany_functions; 33 | 34 | void overview_plugin_queue_update (void); 35 | gboolean overview_geany_supports_left_position (void); 36 | 37 | #endif // OVERVIEW_PLUGIN_H 38 | -------------------------------------------------------------------------------- /overview/overviewprefs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewprefs.c - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | # include "config.h" 25 | #endif 26 | 27 | #include "overviewprefs.h" 28 | #include "overviewcolor.h" 29 | #include "overviewscintilla.h" 30 | #include 31 | #include 32 | 33 | enum 34 | { 35 | PROP_0, 36 | PROP_WIDTH, 37 | PROP_ZOOM, 38 | PROP_SHOW_TOOLTIP, 39 | PROP_SHOW_SCROLLBAR, 40 | PROP_DOUBLE_BUFFERED, 41 | PROP_SCROLL_LINES, 42 | PROP_OVERLAY_ENABLED, 43 | PROP_OVERLAY_COLOR, 44 | PROP_OVERLAY_OUTLINE_COLOR, 45 | PROP_OVERLAY_INVERTED, 46 | PROP_POSITION, 47 | PROP_VISIBLE, 48 | N_PROPERTIES 49 | }; 50 | 51 | struct OverviewPrefs_ 52 | { 53 | GObject parent; 54 | guint width; 55 | gint zoom; 56 | gboolean show_tt; 57 | gboolean show_sb; 58 | gboolean dbl_buf; 59 | gint scr_lines; 60 | gboolean ovl_en; 61 | OverviewColor ovl_clr; 62 | OverviewColor out_clr; 63 | gboolean ovl_inv; 64 | GtkPositionType position; 65 | gboolean visible; 66 | }; 67 | 68 | struct OverviewPrefsClass_ 69 | { 70 | GObjectClass parent_class; 71 | }; 72 | 73 | static void overview_prefs_finalize (GObject *object); 74 | static void overview_prefs_set_property (GObject *object, 75 | guint prop_id, 76 | const GValue *value, 77 | GParamSpec *pspec); 78 | static void overview_prefs_get_property (GObject *object, 79 | guint prop_id, 80 | GValue *value, 81 | GParamSpec *pspec); 82 | 83 | 84 | static GParamSpec *pspecs[N_PROPERTIES] = { NULL }; 85 | 86 | G_DEFINE_TYPE (OverviewPrefs, overview_prefs, G_TYPE_OBJECT) 87 | 88 | static void 89 | overview_prefs_class_init (OverviewPrefsClass *klass) 90 | { 91 | GObjectClass *g_object_class; 92 | 93 | g_object_class = G_OBJECT_CLASS (klass); 94 | 95 | g_object_class->finalize = overview_prefs_finalize; 96 | g_object_class->set_property = overview_prefs_set_property; 97 | g_object_class->get_property = overview_prefs_get_property; 98 | 99 | pspecs[PROP_WIDTH] = g_param_spec_uint ("width", "Width", "Width of the overview", 16, 512, 120, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 100 | pspecs[PROP_ZOOM] = g_param_spec_int ("zoom", "Zoom", "Zoom level of the view", -10, 20, -10, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 101 | pspecs[PROP_SHOW_TOOLTIP] = g_param_spec_boolean ("show-tooltip", "ShowTooltip", "Whether to show informational tooltip over the overview", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 102 | pspecs[PROP_SHOW_SCROLLBAR] = g_param_spec_boolean ("show-scrollbar", "ShowScrollbar", "Whether to show the normal editor scrollbar", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 103 | pspecs[PROP_DOUBLE_BUFFERED] = g_param_spec_boolean ("double-buffered", "DoubleBuffered", "Whether the overview drawing is double-buffered", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 104 | pspecs[PROP_SCROLL_LINES] = g_param_spec_uint ("scroll-lines", "ScrollLines", "The number of lines to scroll the overview by", 1, 512, 1, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 105 | pspecs[PROP_OVERLAY_ENABLED] = g_param_spec_boolean ("overlay-enabled", "OverlayEnabled", "Whether an overlay is drawn overtop the overview", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 106 | pspecs[PROP_OVERLAY_COLOR] = g_param_spec_boxed ("overlay-color", "OverlayColor", "The color of the overlay", OVERVIEW_TYPE_COLOR, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 107 | pspecs[PROP_OVERLAY_OUTLINE_COLOR] = g_param_spec_boxed ("overlay-outline-color", "OverlayOutlineColor", "The color of the outlines drawn around the overlay", OVERVIEW_TYPE_COLOR, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 108 | pspecs[PROP_OVERLAY_INVERTED] = g_param_spec_boolean ("overlay-inverted", "OverlayInverted", "Whether to invert the drawing of the overlay", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 109 | pspecs[PROP_POSITION] = g_param_spec_enum ("position", "Position", "Where to draw the overview", GTK_TYPE_POSITION_TYPE, GTK_POS_RIGHT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 110 | pspecs[PROP_VISIBLE] = g_param_spec_boolean ("visible", "Visible", "Whether the overview is shown", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 111 | 112 | g_object_class_install_properties (g_object_class, N_PROPERTIES, pspecs); 113 | } 114 | 115 | static void 116 | overview_prefs_finalize (GObject *object) 117 | { 118 | g_return_if_fail (OVERVIEW_IS_PREFS (object)); 119 | G_OBJECT_CLASS (overview_prefs_parent_class)->finalize (object); 120 | } 121 | 122 | static void 123 | overview_prefs_set_property (GObject *object, 124 | guint prop_id, 125 | const GValue *value, 126 | GParamSpec *pspec) 127 | { 128 | OverviewPrefs *self = OVERVIEW_PREFS (object); 129 | 130 | switch (prop_id) 131 | { 132 | case PROP_WIDTH: 133 | self->width = g_value_get_uint (value); 134 | g_object_notify (object, "width"); 135 | break; 136 | case PROP_ZOOM: 137 | self->zoom = g_value_get_int (value); 138 | g_object_notify (object, "zoom"); 139 | break; 140 | case PROP_SHOW_TOOLTIP: 141 | self->show_tt = g_value_get_boolean (value); 142 | g_object_notify (object, "show-tooltip"); 143 | break; 144 | case PROP_SHOW_SCROLLBAR: 145 | self->show_sb = g_value_get_boolean (value); 146 | g_object_notify (object, "show-scrollbar"); 147 | break; 148 | case PROP_DOUBLE_BUFFERED: 149 | self->dbl_buf = g_value_get_boolean (value); 150 | g_object_notify (object, "double-buffered"); 151 | break; 152 | case PROP_SCROLL_LINES: 153 | self->scr_lines = g_value_get_uint (value); 154 | g_object_notify (object, "scroll-lines"); 155 | break; 156 | case PROP_OVERLAY_ENABLED: 157 | self->ovl_en = g_value_get_boolean (value); 158 | g_object_notify (object, "overlay-enabled"); 159 | break; 160 | case PROP_OVERLAY_COLOR: 161 | { 162 | OverviewColor *src = g_value_get_boxed (value); 163 | if (src != NULL) 164 | memcpy (&self->ovl_clr, src, sizeof (OverviewColor)); 165 | g_object_notify (object, "overlay-color"); 166 | break; 167 | } 168 | case PROP_OVERLAY_OUTLINE_COLOR: 169 | { 170 | OverviewColor *src = g_value_get_boxed (value); 171 | if (src != NULL) 172 | memcpy (&self->out_clr, src, sizeof (OverviewColor)); 173 | g_object_notify (object, "overlay-outline-color"); 174 | break; 175 | } 176 | case PROP_OVERLAY_INVERTED: 177 | self->ovl_inv = g_value_get_boolean (value); 178 | g_object_notify (G_OBJECT (self), "overlay-inverted"); 179 | break; 180 | case PROP_POSITION: 181 | self->position = g_value_get_enum (value); 182 | g_object_notify (G_OBJECT (self), "position"); 183 | break; 184 | case PROP_VISIBLE: 185 | self->visible = g_value_get_boolean (value); 186 | g_object_notify (G_OBJECT (self), "visible"); 187 | break; 188 | default: 189 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 190 | break; 191 | } 192 | } 193 | 194 | static void 195 | overview_prefs_get_property (GObject *object, 196 | guint prop_id, 197 | GValue *value, 198 | GParamSpec *pspec) 199 | { 200 | OverviewPrefs *self = OVERVIEW_PREFS (object); 201 | 202 | switch (prop_id) 203 | { 204 | case PROP_WIDTH: 205 | g_value_set_uint (value, self->width); 206 | break; 207 | case PROP_ZOOM: 208 | g_value_set_int (value, self->zoom); 209 | break; 210 | case PROP_SHOW_TOOLTIP: 211 | g_value_set_boolean (value, self->show_tt); 212 | break; 213 | case PROP_SHOW_SCROLLBAR: 214 | g_value_set_boolean (value, self->show_sb); 215 | break; 216 | case PROP_DOUBLE_BUFFERED: 217 | g_value_set_boolean (value, self->dbl_buf); 218 | break; 219 | case PROP_SCROLL_LINES: 220 | g_value_set_uint (value, self->scr_lines); 221 | break; 222 | case PROP_OVERLAY_ENABLED: 223 | g_value_set_boolean (value, self->ovl_en); 224 | break; 225 | case PROP_OVERLAY_COLOR: 226 | g_value_set_boxed (value, &self->ovl_clr); 227 | break; 228 | case PROP_OVERLAY_OUTLINE_COLOR: 229 | g_value_set_boxed (value, &self->out_clr); 230 | break; 231 | case PROP_OVERLAY_INVERTED: 232 | g_value_set_boolean (value, self->ovl_inv); 233 | break; 234 | case PROP_POSITION: 235 | g_value_set_enum (value, self->position); 236 | break; 237 | case PROP_VISIBLE: 238 | g_value_set_boolean (value, self->visible); 239 | break; 240 | default: 241 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 242 | break; 243 | } 244 | } 245 | 246 | static void 247 | overview_prefs_init (OverviewPrefs *self) 248 | { 249 | self->position = GTK_POS_RIGHT; 250 | self->visible = TRUE; 251 | } 252 | 253 | OverviewPrefs * 254 | overview_prefs_new (void) 255 | { 256 | return g_object_new (OVERVIEW_TYPE_PREFS, NULL); 257 | } 258 | 259 | gboolean 260 | overview_prefs_load (OverviewPrefs *self, 261 | const gchar *filename, 262 | GError **error) 263 | { 264 | gchar *contents = NULL; 265 | gsize size = 0; 266 | g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE); 267 | g_return_val_if_fail (filename != NULL, FALSE); 268 | if (! g_file_get_contents (filename, &contents, &size, error)) 269 | return FALSE; 270 | if (! overview_prefs_from_data (self, contents, size, error)) 271 | { 272 | g_free (contents); 273 | return FALSE; 274 | } 275 | g_free (contents); 276 | return TRUE; 277 | } 278 | 279 | gboolean 280 | overview_prefs_save (OverviewPrefs *self, 281 | const gchar *filename, 282 | GError **error) 283 | 284 | { 285 | gchar *contents = NULL; 286 | gsize size = 0; 287 | g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE); 288 | g_return_val_if_fail (filename != NULL, FALSE); 289 | contents = overview_prefs_to_data (self, &size, error); 290 | if (contents == NULL) 291 | return FALSE; 292 | if (! g_file_set_contents (filename, contents, size, error)) 293 | { 294 | g_free (contents); 295 | return FALSE; 296 | } 297 | g_free (contents); 298 | return TRUE; 299 | } 300 | 301 | #define GET(T, k, v) \ 302 | do { \ 303 | if (g_key_file_has_key (kf, "overview", k, NULL)) { \ 304 | v = g_key_file_get_##T (kf, "overview", k, error); \ 305 | if (error != NULL && *error != NULL) { \ 306 | g_key_file_free (kf); \ 307 | return FALSE; \ 308 | } else { \ 309 | g_object_notify (G_OBJECT (self), k); \ 310 | } \ 311 | } \ 312 | } while (0) 313 | 314 | gboolean 315 | overview_prefs_from_data (OverviewPrefs *self, 316 | const gchar *contents, 317 | gssize size, 318 | GError **error) 319 | { 320 | GKeyFile *kf; 321 | gchar *pos; 322 | 323 | g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE); 324 | g_return_val_if_fail (contents != NULL, FALSE); 325 | 326 | kf = g_key_file_new (); 327 | 328 | if (! g_key_file_load_from_data (kf, contents, size, 329 | G_KEY_FILE_KEEP_COMMENTS | 330 | G_KEY_FILE_KEEP_TRANSLATIONS, 331 | error)) 332 | { 333 | g_key_file_free (kf); 334 | return FALSE; 335 | } 336 | 337 | GET (uint64, "width", self->width); 338 | GET (integer, "zoom", self->zoom); 339 | GET (boolean, "show-tooltip", self->show_tt); 340 | GET (boolean, "show-scrollbar", self->show_sb); 341 | GET (boolean, "double-buffered", self->dbl_buf); 342 | GET (uint64, "scroll-lines", self->scr_lines); 343 | GET (boolean, "overlay-enabled", self->ovl_en); 344 | GET (boolean, "overlay-inverted", self->ovl_inv); 345 | GET (boolean, "visible", self->visible); 346 | 347 | if (g_key_file_has_key (kf, "overview", "position", NULL)) 348 | { 349 | pos = g_key_file_get_string (kf, "overview", "position", error); 350 | if (error != NULL && *error != NULL) 351 | return FALSE; 352 | if (g_ascii_strcasecmp (pos, "right") == 0) 353 | self->position = GTK_POS_RIGHT; 354 | else if (g_ascii_strcasecmp (pos, "left") == 0) 355 | self->position = GTK_POS_LEFT; 356 | else 357 | { 358 | g_warning ("unknown value '%s' for 'position' key", pos); 359 | self->position = GTK_POS_RIGHT; 360 | } 361 | g_free (pos); 362 | } 363 | 364 | if (g_key_file_has_key (kf, "overview", "overlay-color", NULL) && 365 | g_key_file_has_key (kf, "overview", "overlay-alpha", NULL)) 366 | { 367 | if (! overview_color_from_keyfile (&self->ovl_clr, kf, "overview", "overlay", error)) 368 | { 369 | g_key_file_free (kf); 370 | return FALSE; 371 | } 372 | g_object_notify (G_OBJECT (self), "overlay-color"); 373 | } 374 | 375 | if (g_key_file_has_key (kf, "overview", "overlay-outline-color", NULL) && 376 | g_key_file_has_key (kf, "overview", "overlay-outline-alpha", NULL)) 377 | { 378 | if (! overview_color_from_keyfile (&self->out_clr, kf, "overview", "overlay-outline", error)) 379 | { 380 | g_key_file_free (kf); 381 | return FALSE; 382 | } 383 | g_object_notify (G_OBJECT (self), "overlay-outline-color"); 384 | } 385 | 386 | g_key_file_free (kf); 387 | 388 | return TRUE; 389 | } 390 | 391 | #define SET(T, k, v) g_key_file_set_##T (kf, "overview", k, v) 392 | 393 | gchar * 394 | overview_prefs_to_data (OverviewPrefs *self, 395 | gsize *size, 396 | GError **error) 397 | { 398 | GKeyFile *kf; 399 | gchar *contents; 400 | 401 | g_return_val_if_fail (OVERVIEW_IS_PREFS (self), NULL); 402 | 403 | kf = g_key_file_new (); 404 | 405 | SET (uint64, "width", self->width); 406 | SET (integer, "zoom", self->zoom); 407 | SET (boolean, "show-tooltip", self->show_tt); 408 | SET (boolean, "show-scrollbar", self->show_sb); 409 | SET (boolean, "double-buffered", self->dbl_buf); 410 | SET (uint64, "scroll-lines", self->scr_lines); 411 | SET (boolean, "overlay-enabled", self->ovl_en); 412 | SET (boolean, "overlay-inverted", self->ovl_inv); 413 | SET (boolean, "visible", self->visible); 414 | 415 | g_key_file_set_string (kf, "overview", "position", 416 | self->position == GTK_POS_LEFT ? "left" : "right"); 417 | 418 | overview_color_to_keyfile (&self->ovl_clr, kf, "overview", "overlay"); 419 | overview_color_to_keyfile (&self->out_clr, kf, "overview", "overlay-outline"); 420 | 421 | contents = g_key_file_to_data (kf, size, error); 422 | g_key_file_free (kf); 423 | return contents; 424 | } 425 | 426 | #define BIND(prop) \ 427 | g_object_bind_property (self, prop, sci, prop, G_BINDING_SYNC_CREATE) 428 | 429 | void 430 | overview_prefs_bind_scintilla (OverviewPrefs *self, 431 | GObject *sci) 432 | { 433 | g_return_if_fail (OVERVIEW_IS_PREFS (self)); 434 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (sci)); 435 | 436 | BIND ("width"); 437 | BIND ("zoom"); 438 | BIND ("show-tooltip"); 439 | BIND ("show-scrollbar"); 440 | BIND ("double-buffered"); 441 | BIND ("scroll-lines"); 442 | BIND ("overlay-enabled"); 443 | BIND ("overlay-color"); 444 | BIND ("overlay-outline-color"); 445 | BIND ("overlay-inverted"); 446 | BIND ("visible"); 447 | } 448 | -------------------------------------------------------------------------------- /overview/overviewprefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewprefs.h - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef OVERVIEWPREFS_H_ 24 | #define OVERVIEWPREFS_H_ 1 25 | 26 | #include 27 | 28 | G_BEGIN_DECLS 29 | 30 | #define OVERVIEW_TYPE_PREFS (overview_prefs_get_type ()) 31 | #define OVERVIEW_PREFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVERVIEW_TYPE_PREFS, OverviewPrefs)) 32 | #define OVERVIEW_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OVERVIEW_TYPE_PREFS, OverviewPrefsClass)) 33 | #define OVERVIEW_IS_PREFS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVERVIEW_TYPE_PREFS)) 34 | #define OVERVIEW_IS_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVERVIEW_TYPE_PREFS)) 35 | #define OVERVIEW_PREFS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVERVIEW_TYPE_PREFS, OverviewPrefsClass)) 36 | 37 | typedef struct OverviewPrefs_ OverviewPrefs; 38 | typedef struct OverviewPrefsClass_ OverviewPrefsClass; 39 | 40 | GType overview_prefs_get_type (void); 41 | OverviewPrefs *overview_prefs_new (void); 42 | gboolean overview_prefs_load (OverviewPrefs *prefs, 43 | const gchar *filename, 44 | GError **error); 45 | gboolean overview_prefs_save (OverviewPrefs *prefs, 46 | const gchar *filename, 47 | GError **error); 48 | gboolean overview_prefs_from_data (OverviewPrefs *prefs, 49 | const gchar *contents, 50 | gssize size, 51 | GError **error); 52 | gchar* overview_prefs_to_data (OverviewPrefs *prefs, 53 | gsize *size, 54 | GError **error); 55 | void overview_prefs_bind_scintilla (OverviewPrefs *prefs, 56 | GObject *sci); 57 | 58 | #define OVERVIEW_PREFS_DEFAULT_CONFIG \ 59 | "[overview]\n" \ 60 | "width = 120\n" \ 61 | "zoom = -10\n" \ 62 | "show-tooltip = true\n" \ 63 | "double-buffered = true\n" \ 64 | "scroll-lines = 4\n" \ 65 | "show-scrollbar = true\n" \ 66 | "overlay-enabled = true\n" \ 67 | "overlay-color = #000000\n" \ 68 | "overlay-alpha = 0.10\n" \ 69 | "overlay-outline-color = #000000\n" \ 70 | "overlay-outline-alpha = 0.10\n" \ 71 | "overlay-inverted = true\n" \ 72 | "position = right\n" \ 73 | "visible = true\n" \ 74 | "\n" 75 | 76 | G_END_DECLS 77 | 78 | #endif /* OVERVIEWPREFS_H_ */ 79 | -------------------------------------------------------------------------------- /overview/overviewprefspanel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewprefspanel.c - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | # include "config.h" 25 | #endif 26 | 27 | #include "overviewprefspanel.h" 28 | #include "overviewcolor.h" 29 | #include "overviewplugin.h" 30 | #include "overviewui.h" 31 | 32 | struct OverviewPrefsPanel_ 33 | { 34 | GtkFrame parent; 35 | OverviewPrefs *prefs; 36 | GtkWidget *prefs_table; 37 | GtkWidget *width_spin; 38 | GtkWidget *zoom_spin; 39 | GtkWidget *scr_lines_spin; 40 | GtkWidget *pos_left_check; 41 | GtkWidget *hide_tt_check; 42 | GtkWidget *hide_sb_check; 43 | GtkWidget *ovl_dis_check; 44 | GtkWidget *ovl_inv_check; 45 | GtkWidget *ovl_clr_btn; 46 | GtkWidget *out_clr_btn; 47 | }; 48 | 49 | struct OverviewPrefsPanelClass_ 50 | { 51 | GtkFrameClass parent_class; 52 | }; 53 | 54 | static void overview_prefs_panel_finalize (GObject *object); 55 | 56 | G_DEFINE_TYPE (OverviewPrefsPanel, overview_prefs_panel, GTK_TYPE_FRAME) 57 | 58 | static void 59 | overview_prefs_panel_class_init (OverviewPrefsPanelClass *klass) 60 | { 61 | GObjectClass *g_object_class; 62 | 63 | g_object_class = G_OBJECT_CLASS (klass); 64 | 65 | g_object_class->finalize = overview_prefs_panel_finalize; 66 | 67 | g_signal_new ("prefs-stored", 68 | G_TYPE_FROM_CLASS (g_object_class), 69 | G_SIGNAL_RUN_FIRST, 70 | 0, NULL, NULL, 71 | g_cclosure_marshal_VOID__OBJECT, 72 | G_TYPE_NONE, 73 | 1, OVERVIEW_TYPE_PREFS); 74 | 75 | g_signal_new ("prefs-loaded", 76 | G_TYPE_FROM_CLASS (g_object_class), 77 | G_SIGNAL_RUN_FIRST, 78 | 0, NULL, NULL, 79 | g_cclosure_marshal_VOID__OBJECT, 80 | G_TYPE_NONE, 81 | 1, OVERVIEW_TYPE_PREFS); 82 | } 83 | 84 | static void 85 | overview_prefs_panel_finalize (GObject *object) 86 | { 87 | OverviewPrefsPanel *self; 88 | 89 | g_return_if_fail (OVERVIEW_IS_PREFS_PANEL (object)); 90 | 91 | self = OVERVIEW_PREFS_PANEL (object); 92 | 93 | g_object_unref (self->prefs); 94 | 95 | G_OBJECT_CLASS (overview_prefs_panel_parent_class)->finalize (object); 96 | } 97 | 98 | static GtkWidget * 99 | builder_get_widget (GtkBuilder *builder, 100 | const gchar *name) 101 | { 102 | GObject *result = NULL; 103 | gchar *real_name; 104 | 105 | real_name = g_strdup_printf ("overview-%s", name); 106 | result = gtk_builder_get_object (builder, real_name); 107 | 108 | if (! G_IS_OBJECT (result)) 109 | g_critical ("unable to find widget '%s' in UI file", real_name); 110 | else if (! GTK_IS_WIDGET (result)) 111 | g_critical ("object '%s' in UI file is not a widget", real_name); 112 | 113 | g_free (real_name); 114 | 115 | return (GtkWidget*) result; 116 | } 117 | 118 | static void 119 | overview_prefs_panel_store_prefs (OverviewPrefsPanel *self) 120 | { 121 | guint width; 122 | gint zoom; 123 | guint scr_lines; 124 | gboolean pos_left = FALSE; 125 | OverviewColor ovl_clr = {0,0,0,0}; 126 | OverviewColor out_clr = {0,0,0,0}; 127 | 128 | width = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->width_spin)); 129 | zoom = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->zoom_spin)); 130 | scr_lines = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->scr_lines_spin)); 131 | pos_left = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->pos_left_check)); 132 | overview_color_from_color_button (&ovl_clr, GTK_COLOR_BUTTON (self->ovl_clr_btn)); 133 | overview_color_from_color_button (&out_clr, GTK_COLOR_BUTTON (self->out_clr_btn)); 134 | 135 | g_object_set (self->prefs, 136 | "width", width, 137 | "zoom", zoom, 138 | "scroll-lines", scr_lines, 139 | "position", pos_left ? GTK_POS_LEFT : GTK_POS_RIGHT, 140 | "show-tooltip", !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->hide_tt_check)), 141 | "show-scrollbar", !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->hide_sb_check)), 142 | "overlay-enabled", !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->ovl_dis_check)), 143 | "overlay-inverted", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->ovl_inv_check)), 144 | "overlay-color", &ovl_clr, 145 | "overlay-outline-color", &out_clr, 146 | NULL); 147 | 148 | g_signal_emit_by_name (self, "prefs-stored", self->prefs); 149 | } 150 | 151 | static void 152 | overview_prefs_panel_load_prefs (OverviewPrefsPanel *self) 153 | { 154 | gint zoom = 0; 155 | guint width = 0; 156 | guint scr_lines = 0; 157 | gboolean show_tt = FALSE; 158 | gboolean show_sb = FALSE; 159 | gboolean ovl_en = FALSE; 160 | gboolean ovl_inv = FALSE; 161 | GtkPositionType pos = FALSE; 162 | OverviewColor *ovl_clr = NULL; 163 | OverviewColor *out_clr = NULL; 164 | 165 | g_object_get (self->prefs, 166 | "width", &width, 167 | "zoom", &zoom, 168 | "scroll-lines", &scr_lines, 169 | "position", &pos, 170 | "show-tooltip", &show_tt, 171 | "show-scrollbar", &show_sb, 172 | "overlay-enabled", &ovl_en, 173 | "overlay-inverted", &ovl_inv, 174 | "overlay-color", &ovl_clr, 175 | "overlay-outline-color", &out_clr, 176 | NULL); 177 | 178 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->width_spin), width); 179 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->zoom_spin), zoom); 180 | gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->scr_lines_spin), scr_lines); 181 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->pos_left_check), (pos == GTK_POS_LEFT)); 182 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->hide_tt_check), !show_tt); 183 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->hide_sb_check), !show_sb); 184 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->ovl_inv_check), ovl_inv); 185 | gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->ovl_dis_check), !ovl_en); 186 | overview_color_to_color_button (ovl_clr, GTK_COLOR_BUTTON (self->ovl_clr_btn)); 187 | overview_color_to_color_button (out_clr, GTK_COLOR_BUTTON (self->out_clr_btn)); 188 | 189 | overview_color_free (ovl_clr); 190 | overview_color_free (out_clr); 191 | 192 | g_signal_emit_by_name (self, "prefs-loaded", self->prefs); 193 | } 194 | 195 | static void 196 | overview_prefs_panel_init (OverviewPrefsPanel *self) 197 | { 198 | GtkBuilder *builder; 199 | GError *error = NULL; 200 | GtkWidget *overlay_frame; 201 | 202 | builder = gtk_builder_new (); 203 | if (! gtk_builder_add_from_file (builder, OVERVIEW_PREFS_UI_FILE, &error)) 204 | { 205 | g_critical ("failed to open UI file '%s': %s", OVERVIEW_PREFS_UI_FILE, error->message); 206 | g_error_free (error); 207 | g_object_unref (builder); 208 | return; 209 | } 210 | 211 | self->prefs_table = builder_get_widget (builder, "prefs-table"); 212 | self->width_spin = builder_get_widget (builder, "width-spin"); 213 | self->zoom_spin = builder_get_widget (builder, "zoom-spin"); 214 | self->scr_lines_spin = builder_get_widget (builder, "scroll-lines-spin"); 215 | self->pos_left_check = builder_get_widget (builder, "position-left-check"); 216 | self->hide_tt_check = builder_get_widget (builder, "hide-tooltip-check"); 217 | self->hide_sb_check = builder_get_widget (builder, "hide-scrollbar-check"); 218 | self->ovl_inv_check = builder_get_widget (builder, "overlay-inverted-check"); 219 | self->ovl_clr_btn = builder_get_widget (builder, "overlay-color"); 220 | self->out_clr_btn = builder_get_widget (builder, "overlay-outline-color"); 221 | 222 | // The "Draw over visible area" checkbox hides/shows the "Overlay" frame 223 | self->ovl_dis_check = builder_get_widget (builder, "overlay-disable-check"); 224 | overlay_frame = builder_get_widget (builder, "overlay-frame"); 225 | g_object_bind_property (self->ovl_dis_check, "active", overlay_frame, "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); 226 | 227 | gtk_widget_show_all (self->prefs_table); 228 | gtk_container_add (GTK_CONTAINER (self), self->prefs_table); 229 | g_object_unref (builder); 230 | 231 | #ifndef OVERVIEW_UI_SUPPORTS_LEFT_POSITION 232 | gtk_widget_set_no_show_all (self->pos_left_check, TRUE); 233 | gtk_widget_hide (self->pos_left_check); 234 | #endif 235 | } 236 | 237 | static void 238 | on_host_dialog_response (GtkDialog *dialog, 239 | gint response_id, 240 | OverviewPrefsPanel *self) 241 | { 242 | switch (response_id) 243 | { 244 | case GTK_RESPONSE_APPLY: 245 | case GTK_RESPONSE_OK: 246 | overview_prefs_panel_store_prefs (self); 247 | break; 248 | case GTK_RESPONSE_CANCEL: 249 | default: 250 | break; 251 | } 252 | } 253 | 254 | GtkWidget * 255 | overview_prefs_panel_new (OverviewPrefs *prefs, 256 | GtkDialog *host_dialog) 257 | { 258 | OverviewPrefsPanel *self; 259 | self = g_object_new (OVERVIEW_TYPE_PREFS_PANEL, NULL); 260 | self->prefs = g_object_ref (prefs); 261 | g_signal_connect (host_dialog, "response", G_CALLBACK (on_host_dialog_response), self); 262 | overview_prefs_panel_load_prefs (self); 263 | return GTK_WIDGET (self); 264 | } 265 | -------------------------------------------------------------------------------- /overview/overviewprefspanel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewprefspanel.h - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef OVERVIEWPREFSPANEL_H_ 24 | #define OVERVIEWPREFSPANEL_H_ 1 25 | 26 | #include "overviewprefs.h" 27 | #include 28 | 29 | G_BEGIN_DECLS 30 | 31 | #define OVERVIEW_TYPE_PREFS_PANEL (overview_prefs_panel_get_type ()) 32 | #define OVERVIEW_PREFS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVERVIEW_TYPE_PREFS_PANEL, OverviewPrefsPanel)) 33 | #define OVERVIEW_PREFS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OVERVIEW_TYPE_PREFS_PANEL, OverviewPrefsPanelClass)) 34 | #define OVERVIEW_IS_PREFS_PANEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVERVIEW_TYPE_PREFS_PANEL)) 35 | #define OVERVIEW_IS_PREFS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVERVIEW_TYPE_PREFS_PANEL)) 36 | #define OVERVIEW_PREFS_PANEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVERVIEW_TYPE_PREFS_PANEL, OverviewPrefsPanelClass)) 37 | 38 | typedef struct OverviewPrefsPanel_ OverviewPrefsPanel; 39 | typedef struct OverviewPrefsPanelClass_ OverviewPrefsPanelClass; 40 | 41 | GType overview_prefs_panel_get_type (void); 42 | GtkWidget *overview_prefs_panel_new (OverviewPrefs *prefs, 43 | GtkDialog *host_dialog); 44 | 45 | G_END_DECLS 46 | 47 | #endif /* OVERVIEWPREFSPANEL_H_ */ 48 | -------------------------------------------------------------------------------- /overview/overviewscintilla.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewscintilla.c - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | # include "config.h" 25 | #endif 26 | 27 | #include "overviewscintilla.h" 28 | #include "overviewplugin.h" 29 | #include 30 | 31 | #define OVERVIEW_SCINTILLA_CURSOR GDK_ARROW 32 | #define OVERVIEW_SCINTILLA_CURSOR_CLICK GDK_ARROW 33 | #define OVERVIEW_SCINTILLA_CURSOR_SCROLL GDK_SB_V_DOUBLE_ARROW 34 | #define OVERVIEW_SCINTILLA_ZOOM_MIN -100 35 | #define OVERVIEW_SCINTILLA_ZOOM_MAX 100 36 | #define OVERVIEW_SCINTILLA_ZOOM_DEF -20 37 | #define OVERVIEW_SCINTILLA_WIDTH_MIN 16 38 | #define OVERVIEW_SCINTILLA_WIDTH_MAX 512 39 | #define OVERVIEW_SCINTILLA_WIDTH_DEF 120 40 | #define OVERVIEW_SCINTILLA_SCROLL_LINES 1 41 | 42 | #ifndef SC_MAX_MARGIN 43 | # define SC_MAX_MARGIN 4 44 | #endif 45 | 46 | #define sci_send(sci, msg, wParam, lParam) \ 47 | scintilla_send_message (SCINTILLA (sci), SCI_##msg, (uptr_t)(wParam), (sptr_t)(lParam)) 48 | 49 | static const OverviewColor def_overlay_color = { 0.0, 0.0, 0.0, 0.25 }; 50 | static const OverviewColor def_overlay_outline_color = { 0.0, 0.0, 0.0, 0.0 }; 51 | 52 | enum 53 | { 54 | PROP_0, 55 | PROP_SCINTILLA, 56 | PROP_CURSOR, 57 | PROP_VISIBLE_RECT, 58 | PROP_WIDTH, 59 | PROP_ZOOM, 60 | PROP_SHOW_TOOLTIP, 61 | PROP_OVERLAY_ENABLED, 62 | PROP_OVERLAY_COLOR, 63 | PROP_OVERLAY_OUTLINE_COLOR, 64 | PROP_OVERLAY_INVERTED, 65 | PROP_DOUBLE_BUFFERED, 66 | PROP_SCROLL_LINES, 67 | PROP_SHOW_SCROLLBAR, 68 | N_PROPERTIES, 69 | }; 70 | 71 | struct OverviewScintilla_ 72 | { 73 | ScintillaObject parent; 74 | ScintillaObject *sci; // source scintilla 75 | GtkWidget *canvas; // internal GtkDrawingArea of scintilla 76 | GdkCursorType cursor; // the chosen mouse cursor to use over the scintilla 77 | GdkCursorType active_cursor; // the cursor to draw 78 | GdkRectangle visible_rect; // visible region rectangle 79 | guint width; // width of the overview 80 | gint zoom; // zoom level of scintilla 81 | gboolean show_tooltip; // whether tooltip shown on hover 82 | gboolean overlay_enabled; // whether the visible overlay is drawn 83 | OverviewColor overlay_color; // the color of the visible overlay 84 | OverviewColor overlay_outline_color; // the color of the outline of the overlay 85 | gboolean overlay_inverted;// draw overlay over the visible area instead of around it 86 | gboolean double_buffered; // whether to enable double-buffering on internal scintilla canvas 87 | gint scroll_lines; // number of lines to scroll each scroll-event 88 | gboolean show_scrollbar; // show the main scintilla's scrollbar 89 | gboolean mouse_down; // whether the mouse is down 90 | gulong update_rect; // signal id of idle rect handler 91 | gulong conf_event; // signal id of the configure event on scintilla internal drawing area 92 | GtkWidget *src_canvas; // internal drawing area of main scintilla 93 | }; 94 | 95 | struct OverviewScintillaClass_ 96 | { 97 | ScintillaClass parent_class; 98 | }; 99 | 100 | static GParamSpec *pspecs[N_PROPERTIES] = { NULL }; 101 | 102 | static void overview_scintilla_finalize (GObject *object); 103 | static void overview_scintilla_set_property (GObject *object, 104 | guint prop_id, 105 | const GValue *value, 106 | GParamSpec *pspec); 107 | static void overview_scintilla_get_property (GObject *object, 108 | guint prop_id, 109 | GValue *value, 110 | GParamSpec *pspec); 111 | static void overview_scintilla_set_src_sci (OverviewScintilla *self, 112 | ScintillaObject *sci); 113 | 114 | #if GTK_CHECK_VERSION (3, 0, 0) 115 | static gboolean overview_scintilla_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data); 116 | #else 117 | static gboolean overview_scintilla_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data); 118 | #endif 119 | 120 | G_DEFINE_TYPE (OverviewScintilla, overview_scintilla, scintilla_get_type()) 121 | 122 | static void 123 | overview_scintilla_class_init (OverviewScintillaClass *klass) 124 | { 125 | GObjectClass *g_object_class; 126 | 127 | g_object_class = G_OBJECT_CLASS (klass); 128 | 129 | g_object_class->finalize = overview_scintilla_finalize; 130 | g_object_class->set_property = overview_scintilla_set_property; 131 | g_object_class->get_property = overview_scintilla_get_property; 132 | 133 | pspecs[PROP_SCINTILLA] = 134 | g_param_spec_object ("scintilla", 135 | "Scintilla", 136 | "The source ScintillaObject", 137 | scintilla_get_type (), 138 | G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); 139 | 140 | pspecs[PROP_CURSOR] = 141 | g_param_spec_enum ("cursor", 142 | "Cursor", 143 | "The GdkCursorType to use for the mouse cursor", 144 | GDK_TYPE_CURSOR_TYPE, 145 | OVERVIEW_SCINTILLA_CURSOR, 146 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 147 | 148 | pspecs[PROP_VISIBLE_RECT] = 149 | g_param_spec_boxed ("visible-rect", 150 | "VisibleRect", 151 | "The visible area indication rectangle to draw", 152 | GDK_TYPE_RECTANGLE, 153 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 154 | 155 | pspecs[PROP_WIDTH] = 156 | g_param_spec_uint ("width", 157 | "Width", 158 | "Width of the overview", 159 | OVERVIEW_SCINTILLA_WIDTH_MIN, 160 | OVERVIEW_SCINTILLA_WIDTH_MAX, 161 | OVERVIEW_SCINTILLA_WIDTH_DEF, 162 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 163 | 164 | pspecs[PROP_ZOOM] = 165 | g_param_spec_int ("zoom", 166 | "Zoom", 167 | "The zoom-level of the overview", 168 | OVERVIEW_SCINTILLA_ZOOM_MIN, 169 | OVERVIEW_SCINTILLA_ZOOM_MAX, 170 | OVERVIEW_SCINTILLA_ZOOM_DEF, 171 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 172 | 173 | pspecs[PROP_SHOW_TOOLTIP] = 174 | g_param_spec_boolean ("show-tooltip", 175 | "ShowTooltip", 176 | "Whether to show a tooltip with addition info on mouse over", 177 | TRUE, 178 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 179 | 180 | pspecs[PROP_OVERLAY_ENABLED] = 181 | g_param_spec_boolean ("overlay-enabled", 182 | "OverlayEnabled", 183 | "Whether an overlay is drawn ontop of the overview", 184 | TRUE, 185 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 186 | 187 | pspecs[PROP_OVERLAY_COLOR] = 188 | g_param_spec_boxed ("overlay-color", 189 | "OverlayColor", 190 | "The color of the overlay, if enabled", 191 | OVERVIEW_TYPE_COLOR, 192 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 193 | 194 | pspecs[PROP_OVERLAY_OUTLINE_COLOR] = 195 | g_param_spec_boxed ("overlay-outline-color", 196 | "OverlayOutlineColor", 197 | "The color of the overlay's outline, if enabled", 198 | OVERVIEW_TYPE_COLOR, 199 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 200 | 201 | pspecs[PROP_OVERLAY_INVERTED] = 202 | g_param_spec_boolean ("overlay-inverted", 203 | "OverlayInverted", 204 | "Whether to draw the overlay over the visible area", 205 | TRUE, 206 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 207 | 208 | pspecs[PROP_DOUBLE_BUFFERED] = 209 | g_param_spec_boolean ("double-buffered", 210 | "DoubleBuffered", 211 | "Whether the overview Scintilla's internal canvas is double-buffered", 212 | TRUE, 213 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 214 | 215 | pspecs[PROP_SCROLL_LINES] = 216 | g_param_spec_int ("scroll-lines", 217 | "ScrollLines", 218 | "The number of lines to move each scroll, -1 for default, 0 to disable.", 219 | -1, 100, OVERVIEW_SCINTILLA_SCROLL_LINES, 220 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 221 | 222 | pspecs[PROP_SHOW_SCROLLBAR] = 223 | g_param_spec_boolean ("show-scrollbar", 224 | "ShowScrollbar", 225 | "Whether to show the scrollbar in the main Scintilla", 226 | TRUE, 227 | G_PARAM_CONSTRUCT | G_PARAM_READWRITE); 228 | 229 | g_object_class_install_properties (g_object_class, N_PROPERTIES, pspecs); 230 | } 231 | 232 | static void 233 | overview_scintilla_finalize (GObject *object) 234 | { 235 | OverviewScintilla *self; 236 | 237 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (object)); 238 | 239 | self = OVERVIEW_SCINTILLA (object); 240 | 241 | if (GTK_IS_WIDGET (self->src_canvas) && self->conf_event != 0) 242 | g_signal_handler_disconnect (self->src_canvas, self->conf_event); 243 | 244 | g_object_unref (self->sci); 245 | 246 | G_OBJECT_CLASS (overview_scintilla_parent_class)->finalize (object); 247 | } 248 | 249 | static inline void 250 | cairo_set_source_overlay_color_ (cairo_t *cr, 251 | const OverviewColor *color) 252 | { 253 | cairo_set_source_rgba (cr, color->red, color->green, color->blue, color->alpha); 254 | } 255 | 256 | static inline void 257 | overview_scintilla_draw_real (OverviewScintilla *self, 258 | cairo_t *cr) 259 | { 260 | if (! self->overlay_enabled) 261 | return; 262 | 263 | GtkAllocation alloc; 264 | 265 | gtk_widget_get_allocation (GTK_WIDGET (self->canvas), &alloc); 266 | 267 | cairo_save (cr); 268 | 269 | cairo_set_line_width (cr, 1.0); 270 | 271 | #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) 272 | cairo_set_antialias (cr, CAIRO_ANTIALIAS_GOOD); 273 | #endif 274 | 275 | if (self->overlay_inverted) 276 | { 277 | cairo_set_source_overlay_color_ (cr, &self->overlay_color); 278 | cairo_rectangle (cr, 279 | 0, 280 | self->visible_rect.y, 281 | alloc.width, 282 | self->visible_rect.height); 283 | cairo_fill (cr); 284 | } 285 | else 286 | { 287 | // draw a rectangle at the top and bottom to obscure the non-visible area 288 | cairo_set_source_overlay_color_ (cr, &self->overlay_color); 289 | cairo_rectangle (cr, 0, 0, alloc.width, self->visible_rect.y); 290 | cairo_rectangle (cr, 291 | 0, 292 | self->visible_rect.y + self->visible_rect.height, 293 | alloc.width, 294 | alloc.height - (self->visible_rect.y + self->visible_rect.height)); 295 | cairo_fill (cr); 296 | } 297 | 298 | // draw a highlighting border at top and bottom of visible rect 299 | cairo_set_source_overlay_color_ (cr, &self->overlay_outline_color); 300 | cairo_move_to (cr, self->visible_rect.x + 0.5, self->visible_rect.y + 0.5); 301 | cairo_line_to (cr, self->visible_rect.width, self->visible_rect.y + 0.5); 302 | cairo_move_to (cr, self->visible_rect.x + 0.5, self->visible_rect.y + 0.5 + self->visible_rect.height); 303 | cairo_line_to (cr, self->visible_rect.width, self->visible_rect.y + 0.5 + self->visible_rect.height); 304 | cairo_stroke (cr); 305 | 306 | // draw a left border if there's no scrollbar 307 | if (! overview_scintilla_get_show_scrollbar (self)) 308 | { 309 | cairo_move_to (cr, 0.5, 0.5); 310 | cairo_line_to (cr, 0.5, alloc.height); 311 | cairo_stroke (cr); 312 | } 313 | 314 | cairo_restore (cr); 315 | } 316 | 317 | #if GTK_CHECK_VERSION (3, 0, 0) 318 | static gboolean 319 | overview_scintilla_draw (GtkWidget *widget, 320 | cairo_t *cr, 321 | gpointer user_data) 322 | { 323 | overview_scintilla_draw_real (OVERVIEW_SCINTILLA (user_data), cr); 324 | return FALSE; 325 | } 326 | #else 327 | static gboolean 328 | overview_scintilla_expose_event (GtkWidget *widget, 329 | GdkEventExpose *event, 330 | gpointer user_data) 331 | { 332 | cairo_t *cr; 333 | cr = gdk_cairo_create (gtk_widget_get_window (widget)); 334 | overview_scintilla_draw_real (OVERVIEW_SCINTILLA (user_data), cr); 335 | cairo_destroy (cr); 336 | return FALSE; 337 | } 338 | #endif 339 | 340 | static gboolean 341 | on_focus_in_event (OverviewScintilla *self, 342 | GdkEventFocus *event, 343 | ScintillaObject *sci) 344 | { 345 | sci_send (self, SETREADONLY, 1, 0); 346 | return TRUE; 347 | } 348 | 349 | static gboolean 350 | on_focus_out_event (OverviewScintilla *self, 351 | GdkEventFocus *event, 352 | ScintillaObject *sci) 353 | { 354 | GeanyDocument *doc = g_object_get_data (G_OBJECT (sci), "document"); 355 | if (DOC_VALID (doc)) 356 | sci_send (self, SETREADONLY, doc->readonly, 0); 357 | else 358 | sci_send (self, SETREADONLY, 0, 0); 359 | return TRUE; 360 | } 361 | 362 | static gboolean 363 | on_enter_notify_event (OverviewScintilla *self, 364 | GdkEventCrossing *event, 365 | ScintillaObject *sci) 366 | { 367 | return TRUE; 368 | } 369 | 370 | static gboolean 371 | on_leave_notify_event (OverviewScintilla *self, 372 | GdkEventCrossing *event, 373 | ScintillaObject *sci) 374 | { 375 | return TRUE; 376 | } 377 | 378 | static void 379 | on_each_child (GtkWidget *child, 380 | GList **list) 381 | { 382 | *list = g_list_prepend (*list, child); 383 | } 384 | 385 | static GList * 386 | gtk_container_get_internal_children_ (GtkContainer *cont) 387 | { 388 | GList *list = NULL; 389 | gtk_container_forall (cont, (GtkCallback) on_each_child, &list); 390 | return g_list_reverse (list); 391 | } 392 | 393 | static GtkWidget * 394 | overview_scintilla_find_drawing_area (GtkWidget *root) 395 | { 396 | GtkWidget *da = NULL; 397 | if (GTK_IS_DRAWING_AREA (root)) 398 | da = root; 399 | else if (GTK_IS_CONTAINER (root)) 400 | { 401 | GList *children = gtk_container_get_internal_children_ (GTK_CONTAINER (root)); 402 | for (GList *iter = children; iter != NULL; iter = g_list_next (iter)) 403 | { 404 | GtkWidget *wid = overview_scintilla_find_drawing_area (iter->data); 405 | if (GTK_IS_DRAWING_AREA (wid)) 406 | { 407 | da = wid; 408 | break; 409 | } 410 | } 411 | g_list_free (children); 412 | } 413 | return da; 414 | } 415 | 416 | static gboolean 417 | on_scroll_event (OverviewScintilla *self, 418 | GdkEventScroll *event, 419 | GtkWidget *widget) 420 | { 421 | gint delta = 0; 422 | 423 | if (self->scroll_lines == 0) 424 | return TRUE; 425 | 426 | if (event->direction == GDK_SCROLL_UP) 427 | delta = -(self->scroll_lines); 428 | else if (event->direction == GDK_SCROLL_DOWN) 429 | delta = self->scroll_lines; 430 | 431 | if (delta != 0) 432 | sci_send (self->sci, LINESCROLL, 0, delta); 433 | 434 | return TRUE; 435 | } 436 | 437 | static void 438 | overview_scintilla_goto_point (OverviewScintilla *self, 439 | gint x, 440 | gint y) 441 | { 442 | gint pos; 443 | pos = sci_send (self, POSITIONFROMPOINT, x, y); 444 | if (pos >= 0) 445 | sci_send (self->sci, GOTOPOS, pos, 0); 446 | } 447 | 448 | static void 449 | overview_scintilla_update_cursor (OverviewScintilla *self) 450 | { 451 | if (GTK_IS_WIDGET (self->canvas) && gtk_widget_get_mapped (self->canvas)) 452 | { 453 | GdkCursor *cursor = gdk_cursor_new (self->active_cursor); 454 | gdk_window_set_cursor (gtk_widget_get_window (self->canvas), cursor); 455 | gdk_cursor_unref (cursor); 456 | } 457 | } 458 | 459 | static gboolean 460 | on_button_press_event (OverviewScintilla *self, 461 | GdkEventButton *event, 462 | GtkWidget *widget) 463 | { 464 | self->mouse_down = TRUE; 465 | self->active_cursor = OVERVIEW_SCINTILLA_CURSOR_CLICK; 466 | overview_scintilla_update_cursor (self); 467 | return TRUE; 468 | } 469 | 470 | static gboolean 471 | on_button_release_event (OverviewScintilla *self, 472 | GdkEventButton *event, 473 | GtkWidget *widget) 474 | { 475 | self->mouse_down = FALSE; 476 | self->active_cursor = OVERVIEW_SCINTILLA_CURSOR; 477 | overview_scintilla_update_cursor (self); 478 | overview_scintilla_goto_point (self, event->x, event->y); 479 | return TRUE; 480 | } 481 | 482 | static gboolean 483 | on_motion_notify_event (OverviewScintilla *self, 484 | GdkEventMotion *event, 485 | GtkWidget *widget) 486 | { 487 | if (self->mouse_down) 488 | { 489 | if (self->active_cursor != OVERVIEW_SCINTILLA_CURSOR_SCROLL) 490 | { 491 | self->active_cursor = OVERVIEW_SCINTILLA_CURSOR_SCROLL; 492 | overview_scintilla_update_cursor (self); 493 | } 494 | overview_scintilla_goto_point (self, event->x, event->y); 495 | } 496 | return TRUE; 497 | } 498 | 499 | static gboolean 500 | overview_scintilla_setup_tooltip (OverviewScintilla *self, 501 | gint x, 502 | gint y, 503 | GtkTooltip *tooltip) 504 | { 505 | gint pos; 506 | 507 | if (!self->show_tooltip) 508 | return FALSE; 509 | 510 | pos = sci_send (self, POSITIONFROMPOINT, x, y); 511 | if (pos >= 0) 512 | { 513 | gint line = sci_send (self, LINEFROMPOSITION, pos, 0); 514 | gint column = sci_send (self, GETCOLUMN, pos, 0); 515 | gchar *text = 516 | g_strdup_printf (_("Line %d, Column %d, Position %d"), 517 | line, column, pos); 518 | gtk_tooltip_set_markup (tooltip, text); 519 | g_free (text); 520 | } 521 | else 522 | gtk_tooltip_set_text (tooltip, NULL); 523 | 524 | return TRUE; 525 | } 526 | 527 | static gboolean 528 | on_query_tooltip (OverviewScintilla *self, 529 | gint x, 530 | gint y, 531 | gboolean kbd_mode, 532 | GtkTooltip *tooltip, 533 | GtkWidget *widget) 534 | { 535 | if (!kbd_mode) 536 | return overview_scintilla_setup_tooltip (self, x, y, tooltip); 537 | return FALSE; 538 | } 539 | 540 | static void 541 | overview_scintilla_setup_canvas (OverviewScintilla *self) 542 | { 543 | if (!GTK_IS_WIDGET (self->canvas)) 544 | { 545 | self->canvas = overview_scintilla_find_drawing_area (GTK_WIDGET (self)); 546 | 547 | gtk_widget_add_events (self->canvas, 548 | GDK_EXPOSURE_MASK | 549 | GDK_BUTTON_PRESS_MASK | 550 | GDK_BUTTON_RELEASE_MASK | 551 | GDK_POINTER_MOTION_MASK | 552 | GDK_SCROLL_MASK); 553 | 554 | g_signal_connect_swapped (self->canvas, 555 | "scroll-event", 556 | G_CALLBACK (on_scroll_event), 557 | self); 558 | g_signal_connect_swapped (self->canvas, 559 | "button-press-event", 560 | G_CALLBACK (on_button_press_event), 561 | self); 562 | g_signal_connect_swapped (self->canvas, 563 | "button-release-event", 564 | G_CALLBACK (on_button_release_event), 565 | self); 566 | g_signal_connect_swapped (self->canvas, 567 | "motion-notify-event", 568 | G_CALLBACK (on_motion_notify_event), 569 | self); 570 | g_signal_connect_swapped (self->canvas, 571 | "query-tooltip", 572 | G_CALLBACK (on_query_tooltip), 573 | self); 574 | 575 | gtk_widget_set_has_tooltip (self->canvas, self->show_tooltip); 576 | 577 | #if GTK_CHECK_VERSION (3, 0, 0) 578 | g_signal_connect_after (self->canvas, 579 | "draw", 580 | G_CALLBACK (overview_scintilla_draw), 581 | self); 582 | #else 583 | g_signal_connect_after (self->canvas, 584 | "expose-event", 585 | G_CALLBACK (overview_scintilla_expose_event), 586 | self); 587 | #endif 588 | 589 | } 590 | } 591 | 592 | static void 593 | overview_scintilla_update_rect (OverviewScintilla *self) 594 | { 595 | GtkAllocation alloc; 596 | GdkRectangle rect; 597 | gint first_line, n_lines, last_line; 598 | gint pos_start, pos_end; 599 | gint ystart, yend; 600 | 601 | gtk_widget_get_allocation (GTK_WIDGET (self), &alloc); 602 | 603 | first_line = sci_send (self->sci, GETFIRSTVISIBLELINE, 0, 0); 604 | n_lines = sci_send (self->sci, LINESONSCREEN, 0, 0); 605 | last_line = first_line + n_lines; 606 | 607 | pos_start = sci_send (self, POSITIONFROMLINE, first_line, 0); 608 | pos_end = sci_send (self, POSITIONFROMLINE, last_line, 0); 609 | 610 | ystart = sci_send (self, POINTYFROMPOSITION, 0, pos_start); 611 | yend = sci_send (self, POINTYFROMPOSITION, 0, pos_end); 612 | 613 | if (yend >= alloc.height || yend == 0) 614 | { 615 | n_lines = sci_send (self, GETLINECOUNT, 0, 0); 616 | last_line = n_lines - 1; 617 | pos_end = sci_send (self, POSITIONFROMLINE, last_line, 0); 618 | yend = sci_send (self, POINTYFROMPOSITION, 0, pos_end); 619 | } 620 | 621 | rect.x = 0; 622 | rect.width = alloc.width - 1; 623 | rect.y = ystart; 624 | rect.height = yend - ystart; 625 | 626 | overview_scintilla_set_visible_rect (self, &rect); 627 | } 628 | 629 | static gint 630 | sci_get_midline_ (gpointer sci) 631 | { 632 | gint first, count; 633 | first = sci_send (sci, GETFIRSTVISIBLELINE, 0, 0); 634 | count = sci_send (sci, LINESONSCREEN, 0, 0); 635 | return first + (count / 2); 636 | } 637 | 638 | static void 639 | overview_scintilla_sync_center (OverviewScintilla *self) 640 | { 641 | gint mid_src = sci_get_midline_ (self->sci); 642 | gint mid_dst = sci_get_midline_ (self); 643 | gint delta = mid_src - mid_dst; 644 | sci_send (self, LINESCROLL, 0, delta); 645 | overview_scintilla_update_rect (self); 646 | } 647 | 648 | static gboolean 649 | on_map_event (OverviewScintilla *self, 650 | GdkEventAny *event, 651 | ScintillaObject *sci) 652 | { 653 | overview_scintilla_setup_canvas (self); 654 | 655 | if (GTK_IS_WIDGET (self->canvas) && 656 | gtk_widget_get_double_buffered (self->canvas) != self->double_buffered) 657 | { 658 | gtk_widget_set_double_buffered (self->canvas, self->double_buffered); 659 | self->double_buffered = gtk_widget_get_double_buffered (self->canvas); 660 | } 661 | 662 | overview_scintilla_update_cursor (self); 663 | overview_scintilla_update_rect (self); 664 | 665 | return FALSE; 666 | } 667 | 668 | #define self_connect(name, cb) \ 669 | g_signal_connect_swapped (self, name, G_CALLBACK (cb), self) 670 | 671 | static void 672 | overview_scintilla_init (OverviewScintilla *self) 673 | { 674 | self->sci = NULL; 675 | self->canvas = NULL; 676 | self->cursor = OVERVIEW_SCINTILLA_CURSOR; 677 | self->active_cursor = OVERVIEW_SCINTILLA_CURSOR; 678 | self->update_rect = 0; 679 | self->conf_event = 0; 680 | self->src_canvas = NULL; 681 | self->width = OVERVIEW_SCINTILLA_WIDTH_DEF; 682 | self->zoom = OVERVIEW_SCINTILLA_ZOOM_DEF; 683 | self->mouse_down = FALSE; 684 | self->show_tooltip = TRUE; 685 | self->double_buffered = TRUE; 686 | self->scroll_lines = OVERVIEW_SCINTILLA_SCROLL_LINES; 687 | self->show_scrollbar = TRUE; 688 | self->overlay_inverted = TRUE; 689 | 690 | memset (&self->visible_rect, 0, sizeof (GdkRectangle)); 691 | memcpy (&self->overlay_color, &def_overlay_color, sizeof (OverviewColor)); 692 | memcpy (&self->overlay_outline_color, &def_overlay_outline_color, sizeof (OverviewColor)); 693 | 694 | gtk_widget_add_events (GTK_WIDGET (self), 695 | GDK_EXPOSURE_MASK | 696 | GDK_FOCUS_CHANGE_MASK | 697 | GDK_ENTER_NOTIFY_MASK | 698 | GDK_STRUCTURE_MASK); 699 | 700 | self_connect ("focus-in-event", on_focus_in_event); 701 | self_connect ("focus-out-event", on_focus_out_event); 702 | self_connect ("enter-notify-event", on_enter_notify_event); 703 | self_connect ("leave-notify-event", on_leave_notify_event); 704 | self_connect ("map-event", on_map_event); 705 | } 706 | 707 | static void 708 | overview_scintilla_set_property (GObject *object, 709 | guint prop_id, 710 | const GValue *value, 711 | GParamSpec *pspec) 712 | { 713 | OverviewScintilla *self = OVERVIEW_SCINTILLA (object); 714 | 715 | switch (prop_id) 716 | { 717 | case PROP_SCINTILLA: 718 | overview_scintilla_set_src_sci (self, g_value_get_object (value)); 719 | break; 720 | case PROP_CURSOR: 721 | overview_scintilla_set_cursor (self, g_value_get_enum (value)); 722 | break; 723 | case PROP_VISIBLE_RECT: 724 | overview_scintilla_set_visible_rect (self, g_value_get_boxed (value)); 725 | break; 726 | case PROP_WIDTH: 727 | overview_scintilla_set_width (self, g_value_get_uint (value)); 728 | break; 729 | case PROP_ZOOM: 730 | overview_scintilla_set_zoom (self, g_value_get_int (value)); 731 | break; 732 | case PROP_SHOW_TOOLTIP: 733 | overview_scintilla_set_show_tooltip (self, g_value_get_boolean (value)); 734 | break; 735 | case PROP_OVERLAY_ENABLED: 736 | overview_scintilla_set_overlay_enabled (self, g_value_get_boolean (value)); 737 | break; 738 | case PROP_OVERLAY_COLOR: 739 | overview_scintilla_set_overlay_color (self, g_value_get_boxed (value)); 740 | break; 741 | case PROP_OVERLAY_OUTLINE_COLOR: 742 | overview_scintilla_set_overlay_outline_color (self, g_value_get_boxed (value)); 743 | break; 744 | case PROP_OVERLAY_INVERTED: 745 | overview_scintilla_set_overlay_inverted (self, g_value_get_boolean (value)); 746 | break; 747 | case PROP_DOUBLE_BUFFERED: 748 | overview_scintilla_set_double_buffered (self, g_value_get_boolean (value)); 749 | break; 750 | case PROP_SCROLL_LINES: 751 | overview_scintilla_set_scroll_lines (self, g_value_get_int (value)); 752 | break; 753 | case PROP_SHOW_SCROLLBAR: 754 | overview_scintilla_set_show_scrollbar (self, g_value_get_boolean (value)); 755 | break; 756 | default: 757 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 758 | break; 759 | } 760 | } 761 | 762 | static void 763 | overview_scintilla_get_property (GObject *object, 764 | guint prop_id, 765 | GValue *value, 766 | GParamSpec *pspec) 767 | { 768 | OverviewScintilla *self = OVERVIEW_SCINTILLA (object); 769 | 770 | switch (prop_id) 771 | { 772 | case PROP_SCINTILLA: 773 | g_value_set_object (value, self->sci); 774 | break; 775 | case PROP_CURSOR: 776 | g_value_set_enum (value, overview_scintilla_get_cursor (self)); 777 | break; 778 | case PROP_VISIBLE_RECT: 779 | { 780 | GdkRectangle rect; 781 | overview_scintilla_get_visible_rect (self, &rect); 782 | g_value_set_boxed (value, &rect); 783 | break; 784 | } 785 | case PROP_WIDTH: 786 | g_value_set_uint (value, overview_scintilla_get_width (self)); 787 | break; 788 | case PROP_ZOOM: 789 | g_value_set_int (value, overview_scintilla_get_zoom (self)); 790 | break; 791 | case PROP_SHOW_TOOLTIP: 792 | g_value_set_boolean (value, overview_scintilla_get_show_tooltip (self)); 793 | break; 794 | case PROP_OVERLAY_ENABLED: 795 | g_value_set_boolean (value, overview_scintilla_get_overlay_enabled (self)); 796 | break; 797 | case PROP_OVERLAY_COLOR: 798 | { 799 | OverviewColor color; 800 | overview_scintilla_get_overlay_color (self, &color); 801 | g_value_set_boxed (value, &color); 802 | break; 803 | } 804 | case PROP_OVERLAY_OUTLINE_COLOR: 805 | { 806 | OverviewColor color; 807 | overview_scintilla_get_overlay_outline_color (self, &color); 808 | g_value_set_boxed (value, &color); 809 | break; 810 | } 811 | case PROP_OVERLAY_INVERTED: 812 | g_value_set_boolean (value, overview_scintilla_get_overlay_inverted (self)); 813 | break; 814 | case PROP_DOUBLE_BUFFERED: 815 | g_value_set_boolean (value, overview_scintilla_get_double_buffered (self)); 816 | break; 817 | case PROP_SCROLL_LINES: 818 | g_value_set_int (value, overview_scintilla_get_scroll_lines (self)); 819 | break; 820 | case PROP_SHOW_SCROLLBAR: 821 | g_value_set_boolean (value, overview_scintilla_get_show_scrollbar (self)); 822 | break; 823 | default: 824 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 825 | break; 826 | } 827 | } 828 | 829 | GtkWidget * 830 | overview_scintilla_new (ScintillaObject *src_sci) 831 | { 832 | return g_object_new (OVERVIEW_TYPE_SCINTILLA, "scintilla", src_sci, NULL); 833 | } 834 | 835 | static gchar * 836 | sci_get_font (ScintillaObject *sci, 837 | gint style) 838 | { 839 | gsize len = sci_send (sci, STYLEGETFONT, style, 0); 840 | gchar *name = g_malloc0 (len + 1); 841 | sci_send (sci, STYLEGETFONT, style, name); 842 | return name; 843 | } 844 | 845 | static gboolean 846 | on_src_sci_configure_event (GtkWidget *widget, 847 | GdkEventConfigure *event, 848 | OverviewScintilla *self) 849 | { 850 | overview_scintilla_sync_center (self); 851 | return FALSE; 852 | } 853 | 854 | static gboolean 855 | on_src_sci_map_event (ScintillaObject *sci, 856 | GdkEvent *event, 857 | OverviewScintilla *self) 858 | { 859 | if (self->conf_event == 0) 860 | { 861 | GtkWidget *internal; 862 | internal = overview_scintilla_find_drawing_area (GTK_WIDGET (sci)); 863 | if (GTK_IS_DRAWING_AREA (internal)) 864 | { 865 | self->src_canvas = internal; 866 | self->conf_event = g_signal_connect (self->src_canvas, 867 | "configure-event", 868 | G_CALLBACK (on_src_sci_configure_event), 869 | self); 870 | } 871 | } 872 | return FALSE; 873 | } 874 | 875 | static void 876 | on_src_sci_notify (ScintillaObject *sci, 877 | gpointer unused, 878 | SCNotification *nt, 879 | OverviewScintilla *self) 880 | { 881 | if (nt->nmhdr.code == SCN_UPDATEUI && nt->updated & SC_UPDATE_V_SCROLL) 882 | { 883 | overview_scintilla_sync_center (self); 884 | if (GTK_IS_WIDGET (self->canvas)) 885 | gtk_widget_queue_draw (self->canvas); 886 | } 887 | } 888 | 889 | static void 890 | overview_scintilla_clone_styles (OverviewScintilla *self) 891 | { 892 | ScintillaObject *sci = SCINTILLA (self); 893 | ScintillaObject *src_sci = self->sci; 894 | 895 | for (gint i = 0; i < STYLE_MAX; i++) 896 | { 897 | gchar *font_name = sci_get_font (src_sci, i); 898 | gint font_size = sci_send (src_sci, STYLEGETSIZE, i, 0); 899 | gint weight = sci_send (src_sci, STYLEGETWEIGHT, i, 0); 900 | gboolean italic = sci_send (src_sci, STYLEGETITALIC, i, 0); 901 | gint fg_color = sci_send (src_sci, STYLEGETFORE, i, 0); 902 | gint bg_color = sci_send (src_sci, STYLEGETBACK, i, 0); 903 | 904 | sci_send (sci, STYLESETFONT, i, font_name); 905 | sci_send (sci, STYLESETSIZE, i, font_size); 906 | sci_send (sci, STYLESETWEIGHT, i, weight); 907 | sci_send (sci, STYLESETITALIC, i, italic); 908 | sci_send (sci, STYLESETFORE, i, fg_color); 909 | sci_send (sci, STYLESETBACK, i, bg_color); 910 | sci_send (sci, STYLESETCHANGEABLE, i, 0); 911 | 912 | g_free (font_name); 913 | } 914 | } 915 | 916 | static void 917 | overview_scintilla_queue_draw (OverviewScintilla *self) 918 | { 919 | if (GTK_IS_WIDGET (self->canvas)) 920 | gtk_widget_queue_draw (self->canvas); 921 | else 922 | gtk_widget_queue_draw (GTK_WIDGET (self)); 923 | } 924 | 925 | void 926 | overview_scintilla_sync (OverviewScintilla *self) 927 | { 928 | sptr_t doc_ptr; 929 | 930 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 931 | 932 | doc_ptr = sci_send (self->sci, GETDOCPOINTER, 0, 0); 933 | sci_send (self, SETDOCPOINTER, 0, doc_ptr); 934 | 935 | overview_scintilla_clone_styles (self); 936 | 937 | for (gint i = 0; i < SC_MAX_MARGIN; i++) 938 | sci_send (self, SETMARGINWIDTHN, i, 0); 939 | 940 | sci_send (self, SETVIEWEOL, 0, 0); 941 | sci_send (self, SETVIEWWS, 0, 0); 942 | sci_send (self, SETHSCROLLBAR, 0, 0); 943 | sci_send (self, SETVSCROLLBAR, 0, 0); 944 | sci_send (self, SETZOOM, self->zoom, 0); 945 | sci_send (self, SETCURSOR, SC_CURSORARROW, 0); 946 | sci_send (self, SETENDATLASTLINE, sci_send (self->sci, GETENDATLASTLINE, 0, 0), 0); 947 | sci_send (self, SETMOUSEDOWNCAPTURES, 0, 0); 948 | sci_send (self, SETCARETPERIOD, 0, 0); 949 | sci_send (self, SETCARETWIDTH, 0, 0); 950 | sci_send (self, SETEXTRAASCENT, 0, 0); 951 | sci_send (self, SETEXTRADESCENT, 0, 0); 952 | 953 | sci_send (self->sci, SETVSCROLLBAR, self->show_scrollbar, 0); 954 | 955 | overview_scintilla_update_cursor (self); 956 | overview_scintilla_update_rect (self); 957 | overview_scintilla_sync_center (self); 958 | 959 | overview_scintilla_queue_draw (self); 960 | } 961 | 962 | static void 963 | overview_scintilla_set_src_sci (OverviewScintilla *self, 964 | ScintillaObject *sci) 965 | { 966 | 967 | g_assert (! IS_SCINTILLA (self->sci)); 968 | 969 | self->sci = g_object_ref (sci); 970 | 971 | overview_scintilla_sync (self); 972 | sci_send (self->sci, SETVSCROLLBAR, self->show_scrollbar, 0); 973 | 974 | gtk_widget_add_events (GTK_WIDGET (self->sci), GDK_STRUCTURE_MASK); 975 | plugin_signal_connect (geany_plugin, 976 | G_OBJECT (self->sci), 977 | "map-event", 978 | TRUE, 979 | G_CALLBACK (on_src_sci_map_event), 980 | self); 981 | 982 | plugin_signal_connect (geany_plugin, 983 | G_OBJECT (self->sci), 984 | "sci-notify", 985 | TRUE, 986 | G_CALLBACK (on_src_sci_notify), 987 | self); 988 | 989 | g_object_notify (G_OBJECT (self), "scintilla"); 990 | } 991 | 992 | GdkCursorType 993 | overview_scintilla_get_cursor (OverviewScintilla *self) 994 | { 995 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), GDK_ARROW); 996 | return self->cursor; 997 | } 998 | 999 | void 1000 | overview_scintilla_set_cursor (OverviewScintilla *self, 1001 | GdkCursorType cursor_type) 1002 | { 1003 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1004 | if (cursor_type != self->cursor) 1005 | { 1006 | self->cursor = cursor_type; 1007 | self->active_cursor = cursor_type; 1008 | overview_scintilla_update_cursor (self); 1009 | g_object_notify (G_OBJECT (self), "cursor"); 1010 | } 1011 | } 1012 | 1013 | void 1014 | overview_scintilla_get_visible_rect (OverviewScintilla *self, 1015 | GdkRectangle *rect) 1016 | { 1017 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1018 | g_return_if_fail (rect != NULL); 1019 | 1020 | memcpy (rect, &self->visible_rect, sizeof (GdkRectangle)); 1021 | } 1022 | 1023 | void 1024 | overview_scintilla_set_visible_rect (OverviewScintilla *self, 1025 | const GdkRectangle *rect) 1026 | { 1027 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1028 | 1029 | if (rect == NULL) 1030 | { 1031 | memset (&self->visible_rect, 0, sizeof (GdkRectangle)); 1032 | g_object_notify (G_OBJECT (self), "visible-rect"); 1033 | return; 1034 | } 1035 | 1036 | if (rect->x != self->visible_rect.x || 1037 | rect->y != self->visible_rect.y || 1038 | rect->width != self->visible_rect.width || 1039 | rect->height != self->visible_rect.height) 1040 | { 1041 | memcpy (&self->visible_rect, rect, sizeof (GdkRectangle)); 1042 | if (GTK_IS_WIDGET (self->canvas)) 1043 | gtk_widget_queue_draw (self->canvas); 1044 | g_object_notify (G_OBJECT (self), "visible-rect"); 1045 | } 1046 | } 1047 | 1048 | guint 1049 | overview_scintilla_get_width (OverviewScintilla *self) 1050 | { 1051 | GtkAllocation alloc; 1052 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), 0); 1053 | gtk_widget_get_allocation (GTK_WIDGET (self), &alloc); 1054 | return alloc.width; 1055 | } 1056 | 1057 | void 1058 | overview_scintilla_set_width (OverviewScintilla *self, 1059 | guint width) 1060 | { 1061 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1062 | gtk_widget_set_size_request (GTK_WIDGET (self), width, -1); 1063 | } 1064 | 1065 | gint 1066 | overview_scintilla_get_zoom (OverviewScintilla *self) 1067 | { 1068 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), 0); 1069 | self->zoom = sci_send (self, GETZOOM, 0, 0); 1070 | return self->zoom; 1071 | } 1072 | 1073 | void 1074 | overview_scintilla_set_zoom (OverviewScintilla *self, 1075 | gint zoom) 1076 | { 1077 | gint old_zoom; 1078 | 1079 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1080 | g_return_if_fail (zoom >= OVERVIEW_SCINTILLA_ZOOM_MIN && 1081 | zoom <= OVERVIEW_SCINTILLA_ZOOM_MAX); 1082 | 1083 | old_zoom = sci_send (self, GETZOOM, 0, 0); 1084 | if (zoom != old_zoom) 1085 | { 1086 | sci_send (self, SETZOOM, zoom, 0); 1087 | self->zoom = sci_send (self, GETZOOM, 0, 0); 1088 | if (self->zoom != old_zoom) 1089 | { 1090 | overview_scintilla_sync_center (self); 1091 | g_object_notify (G_OBJECT (self), "zoom"); 1092 | } 1093 | } 1094 | } 1095 | 1096 | gboolean 1097 | overview_scintilla_get_show_tooltip (OverviewScintilla *self) 1098 | { 1099 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), FALSE); 1100 | return self->show_tooltip; 1101 | } 1102 | 1103 | void 1104 | overview_scintilla_set_show_tooltip (OverviewScintilla *self, 1105 | gboolean show) 1106 | { 1107 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1108 | 1109 | if (show != self->show_tooltip) 1110 | { 1111 | self->show_tooltip = show; 1112 | if (GTK_IS_WIDGET (self->canvas)) 1113 | gtk_widget_set_has_tooltip (self->canvas, self->show_tooltip); 1114 | g_object_notify (G_OBJECT (self), "show-tooltip"); 1115 | } 1116 | } 1117 | 1118 | gboolean 1119 | overview_scintilla_get_overlay_enabled (OverviewScintilla *self) 1120 | { 1121 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), FALSE); 1122 | return self->overlay_enabled; 1123 | } 1124 | 1125 | void 1126 | overview_scintilla_set_overlay_enabled (OverviewScintilla *self, 1127 | gboolean enabled) 1128 | { 1129 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1130 | 1131 | if (enabled != self->overlay_enabled) 1132 | { 1133 | self->overlay_enabled = enabled; 1134 | if (GTK_IS_WIDGET (self->canvas)) 1135 | gtk_widget_queue_draw (self->canvas); 1136 | g_object_notify (G_OBJECT (self), "overlay-enabled"); 1137 | } 1138 | } 1139 | 1140 | void 1141 | overview_scintilla_get_overlay_color (OverviewScintilla *self, 1142 | OverviewColor *color) 1143 | { 1144 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1145 | g_return_if_fail (color != NULL); 1146 | memcpy (color, &self->overlay_color, sizeof (OverviewColor)); 1147 | } 1148 | 1149 | void 1150 | overview_scintilla_set_overlay_color (OverviewScintilla *self, 1151 | const OverviewColor *color) 1152 | { 1153 | gboolean changed = FALSE; 1154 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1155 | 1156 | if (color == NULL) 1157 | { 1158 | memcpy (&self->overlay_color, &def_overlay_color, sizeof (OverviewColor)); 1159 | changed = TRUE; 1160 | } 1161 | else if (!overview_color_equal (color, &self->overlay_color)) 1162 | { 1163 | memcpy (&self->overlay_color, color, sizeof (OverviewColor)); 1164 | changed = TRUE; 1165 | } 1166 | 1167 | if (changed) 1168 | { 1169 | if (GTK_IS_WIDGET (self->canvas)) 1170 | gtk_widget_queue_draw (self->canvas); 1171 | g_object_notify (G_OBJECT (self), "overlay-color"); 1172 | } 1173 | } 1174 | 1175 | void 1176 | overview_scintilla_get_overlay_outline_color (OverviewScintilla *self, 1177 | OverviewColor *color) 1178 | { 1179 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1180 | g_return_if_fail (color != NULL); 1181 | memcpy (color, &self->overlay_outline_color, sizeof (OverviewColor)); 1182 | } 1183 | 1184 | void 1185 | overview_scintilla_set_overlay_outline_color (OverviewScintilla *self, 1186 | const OverviewColor *color) 1187 | { 1188 | gboolean changed = FALSE; 1189 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1190 | 1191 | if (color == NULL) 1192 | { 1193 | memcpy (&self->overlay_outline_color, &def_overlay_outline_color, sizeof (OverviewColor)); 1194 | changed = TRUE; 1195 | } 1196 | else if (!overview_color_equal (color, &self->overlay_outline_color)) 1197 | { 1198 | memcpy (&self->overlay_outline_color, color, sizeof (OverviewColor)); 1199 | changed = TRUE; 1200 | } 1201 | 1202 | if (changed) 1203 | { 1204 | if (GTK_IS_WIDGET (self->canvas)) 1205 | gtk_widget_queue_draw (self->canvas); 1206 | g_object_notify (G_OBJECT (self), "overlay-outline-color"); 1207 | } 1208 | } 1209 | 1210 | gboolean 1211 | overview_scintilla_get_overlay_inverted (OverviewScintilla *self) 1212 | { 1213 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), FALSE); 1214 | return self->overlay_inverted; 1215 | } 1216 | 1217 | void 1218 | overview_scintilla_set_overlay_inverted (OverviewScintilla *self, 1219 | gboolean inverted) 1220 | { 1221 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1222 | 1223 | if (inverted != self->overlay_inverted) 1224 | { 1225 | self->overlay_inverted = inverted; 1226 | overview_scintilla_queue_draw (self); 1227 | g_object_notify (G_OBJECT (self), "overlay-inverted"); 1228 | } 1229 | } 1230 | 1231 | gboolean 1232 | overview_scintilla_get_double_buffered (OverviewScintilla *self) 1233 | { 1234 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), FALSE); 1235 | if (GTK_IS_WIDGET (self->canvas)) 1236 | self->double_buffered = gtk_widget_get_double_buffered (self->canvas); 1237 | return self->double_buffered; 1238 | } 1239 | 1240 | void 1241 | overview_scintilla_set_double_buffered (OverviewScintilla *self, 1242 | gboolean enabled) 1243 | { 1244 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1245 | 1246 | if (enabled != self->double_buffered) 1247 | { 1248 | self->double_buffered = enabled; 1249 | if (GTK_IS_WIDGET (self->canvas)) 1250 | { 1251 | gtk_widget_set_double_buffered (self->canvas, self->double_buffered); 1252 | self->double_buffered = gtk_widget_get_double_buffered (self->canvas); 1253 | } 1254 | if (self->double_buffered == enabled) 1255 | g_object_notify (G_OBJECT (self), "double-buffered"); 1256 | } 1257 | } 1258 | 1259 | gint 1260 | overview_scintilla_get_scroll_lines (OverviewScintilla *self) 1261 | { 1262 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), -1); 1263 | return self->scroll_lines; 1264 | } 1265 | 1266 | void 1267 | overview_scintilla_set_scroll_lines (OverviewScintilla *self, 1268 | gint lines) 1269 | { 1270 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1271 | 1272 | if (lines < 0) 1273 | lines = OVERVIEW_SCINTILLA_SCROLL_LINES; 1274 | 1275 | if (lines != self->scroll_lines) 1276 | { 1277 | self->scroll_lines = lines; 1278 | g_object_notify (G_OBJECT (self), "scroll-lines"); 1279 | } 1280 | } 1281 | 1282 | gboolean 1283 | overview_scintilla_get_show_scrollbar (OverviewScintilla *self) 1284 | { 1285 | g_return_val_if_fail (OVERVIEW_IS_SCINTILLA (self), FALSE); 1286 | return self->show_scrollbar; 1287 | } 1288 | 1289 | void 1290 | overview_scintilla_set_show_scrollbar (OverviewScintilla *self, 1291 | gboolean show) 1292 | { 1293 | g_return_if_fail (OVERVIEW_IS_SCINTILLA (self)); 1294 | 1295 | if (show != self->show_scrollbar) 1296 | { 1297 | self->show_scrollbar = show; 1298 | sci_send (self->sci, SETVSCROLLBAR, self->show_scrollbar, 0); 1299 | gtk_widget_queue_draw (GTK_WIDGET (self->sci)); 1300 | g_object_notify (G_OBJECT (self), "show-scrollbar"); 1301 | } 1302 | } 1303 | -------------------------------------------------------------------------------- /overview/overviewscintilla.h: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewscintilla.h - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef OVERVIEWSCINTILLA_H_ 24 | #define OVERVIEWSCINTILLA_H_ 1 25 | 26 | #include "overviewplugin.h" 27 | #include "overviewcolor.h" 28 | 29 | G_BEGIN_DECLS 30 | 31 | #define OVERVIEW_TYPE_SCINTILLA (overview_scintilla_get_type ()) 32 | #define OVERVIEW_SCINTILLA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVERVIEW_TYPE_SCINTILLA, OverviewScintilla)) 33 | #define OVERVIEW_SCINTILLA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), OVERVIEW_TYPE_SCINTILLA, OverviewScintillaClass)) 34 | #define OVERVIEW_IS_SCINTILLA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVERVIEW_TYPE_SCINTILLA)) 35 | #define OVERVIEW_IS_SCINTILLA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVERVIEW_TYPE_SCINTILLA)) 36 | #define OVERVIEW_SCINTILLA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), OVERVIEW_TYPE_SCINTILLA, OverviewScintillaClass)) 37 | 38 | typedef struct OverviewScintilla_ OverviewScintilla; 39 | typedef struct OverviewScintillaClass_ OverviewScintillaClass; 40 | 41 | GType overview_scintilla_get_type (void); 42 | GtkWidget *overview_scintilla_new (ScintillaObject *src_sci); 43 | void overview_scintilla_sync (OverviewScintilla *sci); 44 | GdkCursorType overview_scintilla_get_cursor (OverviewScintilla *sci); 45 | void overview_scintilla_set_cursor (OverviewScintilla *sci, 46 | GdkCursorType cursor_type); 47 | void overview_scintilla_get_visible_rect (OverviewScintilla *sci, 48 | GdkRectangle *rect); 49 | void overview_scintilla_set_visible_rect (OverviewScintilla *sci, 50 | const GdkRectangle *rect); 51 | guint overview_scintilla_get_width (OverviewScintilla *sci); 52 | void overview_scintilla_set_width (OverviewScintilla *sci, 53 | guint width); 54 | gint overview_scintilla_get_zoom (OverviewScintilla *sci); 55 | void overview_scintilla_set_zoom (OverviewScintilla *sci, 56 | gint zoom); 57 | gboolean overview_scintilla_get_show_tooltip (OverviewScintilla *sci); 58 | void overview_scintilla_set_show_tooltip (OverviewScintilla *sci, 59 | gboolean show); 60 | gboolean overview_scintilla_get_overlay_enabled (OverviewScintilla *sci); 61 | void overview_scintilla_set_overlay_enabled (OverviewScintilla *sci, 62 | gboolean enabled); 63 | void overview_scintilla_get_overlay_color (OverviewScintilla *sci, 64 | OverviewColor *color); 65 | void overview_scintilla_set_overlay_color (OverviewScintilla *sci, 66 | const OverviewColor *color); 67 | void overview_scintilla_get_overlay_outline_color (OverviewScintilla *sci, 68 | OverviewColor *color); 69 | void overview_scintilla_set_overlay_outline_color (OverviewScintilla *sci, 70 | const OverviewColor *color); 71 | gboolean overview_scintilla_get_overlay_inverted (OverviewScintilla *sci); 72 | void overview_scintilla_set_overlay_inverted (OverviewScintilla *sci, 73 | gboolean inverted); 74 | gboolean overview_scintilla_get_double_buffered (OverviewScintilla *sci); 75 | void overview_scintilla_set_double_buffered (OverviewScintilla *sci, 76 | gboolean enabled); 77 | gint overview_scintilla_get_scroll_lines (OverviewScintilla *sci); 78 | void overview_scintilla_set_scroll_lines (OverviewScintilla *sci, 79 | gint lines); 80 | gboolean overview_scintilla_get_show_scrollbar (OverviewScintilla *sci); 81 | void overview_scintilla_set_show_scrollbar (OverviewScintilla *sci, 82 | gboolean show); 83 | 84 | G_END_DECLS 85 | 86 | #endif /* OVERVIEWSCINTILLA_H_ */ 87 | -------------------------------------------------------------------------------- /overview/overviewui.c: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewui.c - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifdef HAVE_CONFIG_H 24 | # include "config.h" 25 | #endif 26 | 27 | #include "overviewui.h" 28 | #include "overviewplugin.h" 29 | #include "overviewscintilla.h" 30 | 31 | typedef void (*DocForEachFunc) (ScintillaObject *src_sci, 32 | OverviewScintilla *overview); 33 | 34 | static void overview_ui_hijack_all_editor_views (void); 35 | static void overview_ui_restore_all_editor_views (void); 36 | static void overview_ui_update_all_editor_views (void); 37 | 38 | static OverviewPrefs *overview_ui_prefs = NULL; 39 | static GtkWidget *overview_ui_menu_sep = NULL; 40 | static GtkWidget *overview_ui_menu_item = NULL; 41 | 42 | static inline void 43 | overview_ui_scintilla_foreach (DocForEachFunc callback) 44 | { 45 | guint i; 46 | foreach_document (i) 47 | { 48 | GeanyDocument *doc = documents[i]; 49 | ScintillaObject *src_sci; 50 | OverviewScintilla *overview; 51 | src_sci = doc->editor->sci; 52 | overview = g_object_get_data (G_OBJECT (src_sci), "overview"); 53 | if (IS_SCINTILLA (doc->editor->sci)) 54 | callback (src_sci, overview); 55 | else 56 | g_critical ("enumerating invalid scintilla editor widget"); 57 | } 58 | } 59 | 60 | static inline gboolean 61 | overview_ui_position_is_left (void) 62 | { 63 | GtkPositionType position; 64 | g_object_get (overview_ui_prefs, "position", &position, NULL); 65 | return (position == GTK_POS_LEFT); 66 | } 67 | 68 | static inline void 69 | overview_ui_container_add_expanded (GtkContainer *container, 70 | GtkWidget *widget) 71 | { 72 | gtk_container_add (container, widget); 73 | /* GTK+ 3 doesn't expand by default anymore */ 74 | #if GTK_CHECK_VERSION (3, 0, 0) 75 | g_object_set (widget, "expand", TRUE, NULL); 76 | #endif 77 | } 78 | 79 | static void 80 | overview_ui_hijack_editor_view (ScintillaObject *src_sci, 81 | OverviewScintilla *null_and_unused) 82 | { 83 | GtkWidget *parent; 84 | GtkWidget *container; 85 | GtkWidget *overview; 86 | gboolean on_left; 87 | 88 | g_assert (g_object_get_data (G_OBJECT (src_sci), "overview") == NULL); 89 | 90 | parent = gtk_widget_get_parent (GTK_WIDGET (src_sci)); 91 | container = gtk_hbox_new (FALSE, 0); 92 | overview = overview_scintilla_new (src_sci); 93 | 94 | overview_prefs_bind_scintilla (overview_ui_prefs, G_OBJECT (overview)); 95 | gtk_widget_set_no_show_all (overview, TRUE); 96 | 97 | g_object_set_data (G_OBJECT (src_sci), "overview", overview); 98 | 99 | on_left = overview_ui_position_is_left (); 100 | #ifndef OVERVIEW_UI_SUPPORTS_LEFT_POSITION 101 | if (on_left) 102 | { 103 | g_critical ("Refusing to add Overview into left position because " 104 | "your Geany version isn't new enough to support this " 105 | "without crashing hard."); 106 | on_left = FALSE; 107 | } 108 | #endif 109 | 110 | g_object_ref (src_sci); 111 | gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (src_sci)); 112 | 113 | if (on_left) 114 | { 115 | gtk_box_pack_start (GTK_BOX (container), overview, FALSE, TRUE, 0); 116 | gtk_box_pack_start (GTK_BOX (container), GTK_WIDGET (src_sci), TRUE, TRUE, 0); 117 | } 118 | else 119 | { 120 | gtk_box_pack_start (GTK_BOX (container), GTK_WIDGET (src_sci), TRUE, TRUE, 0); 121 | gtk_box_pack_start (GTK_BOX (container), overview, FALSE, TRUE, 0); 122 | } 123 | 124 | overview_ui_container_add_expanded (GTK_CONTAINER (parent), container); 125 | g_object_unref (src_sci); 126 | 127 | gtk_widget_show_all (container); 128 | } 129 | 130 | static void 131 | overview_ui_hijack_all_editor_views (void) 132 | { 133 | overview_ui_scintilla_foreach (overview_ui_hijack_editor_view); 134 | } 135 | 136 | static void 137 | overview_ui_restore_editor_view (ScintillaObject *src_sci, 138 | OverviewScintilla *overview) 139 | { 140 | GtkWidget *old_parent = gtk_widget_get_parent (GTK_WIDGET (src_sci)); 141 | GtkWidget *new_parent = gtk_widget_get_parent (old_parent); 142 | g_object_ref (src_sci); 143 | g_object_set_data (G_OBJECT (src_sci), "overview", NULL); 144 | gtk_container_remove (GTK_CONTAINER (old_parent), GTK_WIDGET (src_sci)); 145 | gtk_container_remove (GTK_CONTAINER (new_parent), old_parent); 146 | overview_ui_container_add_expanded (GTK_CONTAINER (new_parent), GTK_WIDGET (src_sci)); 147 | g_object_unref (src_sci); 148 | } 149 | 150 | static void 151 | overview_ui_restore_all_editor_views (void) 152 | { 153 | overview_ui_scintilla_foreach (overview_ui_restore_editor_view); 154 | } 155 | 156 | static void 157 | overview_ui_update_editor_view (ScintillaObject *src_sci, 158 | OverviewScintilla *overview) 159 | { 160 | GtkWidget *parent; 161 | gboolean on_left; 162 | 163 | on_left = overview_ui_position_is_left (); 164 | #ifndef OVERVIEW_UI_SUPPORTS_LEFT_POSITION 165 | if (on_left) 166 | { 167 | g_critical ("Refusing to swap Overview into left position because " 168 | "your Geany version isn't new enough to support this " 169 | "without crashing hard."); 170 | on_left = FALSE; 171 | } 172 | #endif 173 | 174 | parent = gtk_widget_get_parent (GTK_WIDGET (src_sci)); 175 | 176 | g_object_ref (src_sci); 177 | g_object_ref (overview); 178 | 179 | gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (src_sci)); 180 | gtk_container_remove (GTK_CONTAINER (parent), GTK_WIDGET (overview)); 181 | 182 | if (on_left) 183 | { 184 | gtk_box_pack_start (GTK_BOX (parent), GTK_WIDGET (overview), FALSE, TRUE, 0); 185 | gtk_box_pack_start (GTK_BOX (parent), GTK_WIDGET (src_sci), TRUE, TRUE, 0); 186 | } 187 | else 188 | { 189 | gtk_box_pack_start (GTK_BOX (parent), GTK_WIDGET (src_sci), TRUE, TRUE, 0); 190 | gtk_box_pack_start (GTK_BOX (parent), GTK_WIDGET (overview), FALSE, TRUE, 0); 191 | } 192 | 193 | gtk_widget_show_all (parent); 194 | 195 | g_object_unref (overview); 196 | g_object_unref (src_sci); 197 | 198 | overview_scintilla_sync (overview); 199 | } 200 | 201 | void 202 | overview_ui_update_all_editor_views (void) 203 | { 204 | overview_ui_scintilla_foreach (overview_ui_update_editor_view); 205 | } 206 | 207 | GtkWidget * 208 | overview_ui_get_menu_item (void) 209 | { 210 | g_return_val_if_fail (GTK_IS_MENU_ITEM (overview_ui_menu_item), NULL); 211 | return overview_ui_menu_item; 212 | } 213 | 214 | static inline OverviewScintilla * 215 | overview_scintilla_from_document (GeanyDocument *doc) 216 | { 217 | if (DOC_VALID (doc)) 218 | { 219 | ScintillaObject *src_sci = doc->editor->sci; 220 | if (IS_SCINTILLA (src_sci)) 221 | return g_object_get_data (G_OBJECT (src_sci), "overview"); 222 | } 223 | return NULL; 224 | } 225 | 226 | static void 227 | on_document_open_new (G_GNUC_UNUSED GObject *unused, 228 | GeanyDocument *doc, 229 | G_GNUC_UNUSED gpointer user_data) 230 | { 231 | g_object_set_data (G_OBJECT (doc->editor->sci), "overview-document", doc); 232 | overview_ui_hijack_editor_view (doc->editor->sci, NULL); 233 | overview_ui_queue_update (); 234 | } 235 | 236 | static void 237 | on_document_activate_reload (G_GNUC_UNUSED GObject *unused, 238 | G_GNUC_UNUSED GeanyDocument *doc, 239 | G_GNUC_UNUSED gpointer user_data) 240 | { 241 | overview_ui_queue_update (); 242 | } 243 | 244 | static void 245 | on_document_close (G_GNUC_UNUSED GObject *unused, 246 | GeanyDocument *doc, 247 | G_GNUC_UNUSED gpointer user_data) 248 | { 249 | OverviewScintilla *overview; 250 | overview = overview_scintilla_from_document (doc); 251 | overview_ui_restore_editor_view (doc->editor->sci, overview); 252 | } 253 | 254 | static gint 255 | overview_ui_get_menu_item_pos (GtkWidget *menu, 256 | GtkWidget *item_before) 257 | { 258 | GList *children; 259 | gint pos = 0; 260 | children = gtk_container_get_children (GTK_CONTAINER (menu)); 261 | for (GList *iter = children; iter != NULL; iter = g_list_next (iter), pos++) 262 | { 263 | if (iter->data == item_before) 264 | break; 265 | } 266 | g_list_free (children); 267 | return pos + 1; 268 | } 269 | 270 | static void 271 | overview_ui_add_menu_item (void) 272 | { 273 | static const gchar *view_menu_name = "menu_view1_menu"; 274 | static const gchar *prev_item_name = "menu_show_sidebar1"; 275 | GtkWidget *main_window = geany_data->main_widgets->window; 276 | GtkWidget *view_menu; 277 | GtkWidget *prev_item; 278 | gint item_pos; 279 | gboolean visible = FALSE; 280 | 281 | view_menu = ui_lookup_widget (main_window, view_menu_name); 282 | if (! GTK_IS_MENU (view_menu)) 283 | { 284 | g_critical ("failed to locate the View menu (%s) in Geany's main menu", 285 | view_menu_name); 286 | return; 287 | } 288 | 289 | overview_ui_menu_item = gtk_check_menu_item_new_with_label (_("Show Overview")); 290 | prev_item = ui_lookup_widget (main_window, prev_item_name); 291 | if (! GTK_IS_MENU_ITEM (prev_item)) 292 | { 293 | g_critical ("failed to locate the Show Sidebar menu item (%s) in Geany's UI", 294 | prev_item_name); 295 | overview_ui_menu_sep = gtk_separator_menu_item_new (); 296 | gtk_menu_shell_append (GTK_MENU_SHELL (view_menu), overview_ui_menu_sep); 297 | gtk_menu_shell_append (GTK_MENU_SHELL (view_menu), overview_ui_menu_item); 298 | gtk_widget_show (overview_ui_menu_sep); 299 | } 300 | else 301 | { 302 | item_pos = overview_ui_get_menu_item_pos (view_menu, prev_item); 303 | overview_ui_menu_sep = NULL; 304 | gtk_menu_shell_insert (GTK_MENU_SHELL (view_menu), overview_ui_menu_item, item_pos); 305 | } 306 | 307 | g_object_get (overview_ui_prefs, "visible", &visible, NULL); 308 | gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (overview_ui_menu_item), visible); 309 | g_object_bind_property (overview_ui_menu_item, "active", 310 | overview_ui_prefs, "visible", 311 | G_BINDING_DEFAULT); 312 | 313 | gtk_widget_show (overview_ui_menu_item); 314 | } 315 | 316 | static void 317 | on_position_pref_notify (OverviewPrefs *prefs, 318 | GParamSpec *pspec, 319 | gpointer user_data) 320 | { 321 | overview_ui_update_all_editor_views (); 322 | } 323 | 324 | void 325 | overview_ui_init (OverviewPrefs *prefs) 326 | { 327 | overview_ui_prefs = g_object_ref (prefs); 328 | 329 | overview_ui_add_menu_item (); 330 | overview_ui_hijack_all_editor_views (); 331 | 332 | g_signal_connect (prefs, "notify::position", 333 | G_CALLBACK (on_position_pref_notify), NULL); 334 | 335 | plugin_signal_connect (geany_plugin, NULL, "document-new", TRUE, G_CALLBACK (on_document_open_new), NULL); 336 | plugin_signal_connect (geany_plugin, NULL, "document-open", TRUE, G_CALLBACK (on_document_open_new), NULL); 337 | plugin_signal_connect (geany_plugin, NULL, "document-activate", TRUE, G_CALLBACK (on_document_activate_reload), NULL); 338 | plugin_signal_connect (geany_plugin, NULL, "document-reload", TRUE, G_CALLBACK (on_document_activate_reload), NULL); 339 | plugin_signal_connect (geany_plugin, NULL, "document-close", TRUE, G_CALLBACK (on_document_close), NULL); 340 | 341 | } 342 | 343 | void 344 | overview_ui_deinit (void) 345 | { 346 | overview_ui_restore_all_editor_views (); 347 | 348 | if (GTK_IS_WIDGET (overview_ui_menu_sep)) 349 | gtk_widget_destroy (overview_ui_menu_sep); 350 | gtk_widget_destroy (overview_ui_menu_item); 351 | 352 | if (OVERVIEW_IS_PREFS (overview_ui_prefs)) 353 | g_object_unref (overview_ui_prefs); 354 | overview_ui_prefs = NULL; 355 | } 356 | 357 | static gboolean 358 | on_update_overview_later (gpointer user_data) 359 | { 360 | GeanyDocument *doc; 361 | doc = document_get_current (); 362 | if (DOC_VALID (doc)) 363 | { 364 | OverviewScintilla *overview; 365 | overview = g_object_get_data (G_OBJECT (doc->editor->sci), "overview"); 366 | if (OVERVIEW_IS_SCINTILLA (overview)) 367 | overview_scintilla_sync (overview); 368 | } 369 | return FALSE; 370 | } 371 | 372 | void 373 | overview_ui_queue_update (void) 374 | { 375 | g_idle_add_full (G_PRIORITY_LOW, on_update_overview_later, NULL, NULL); 376 | } 377 | -------------------------------------------------------------------------------- /overview/overviewui.h: -------------------------------------------------------------------------------- 1 | /* 2 | * overviewui.h - This file is part of the Geany Overview plugin 3 | * 4 | * Copyright (c) 2015 Matthew Brush 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef OVERVIEWUI_H_ 24 | #define OVERVIEWUI_H_ 25 | 26 | #include "overviewprefs.h" 27 | #include "overviewplugin.h" 28 | 29 | // This should match the API version of when the patch gets applied to 30 | // make putting overview on left work. 31 | #define OVERVIEW_SCI_HUNTING_PATCH_API 224 32 | 33 | #if GEANY_API_VERSION >= OVERVIEW_SCI_HUNTING_PATCH_API 34 | # define OVERVIEW_UI_SUPPORTS_LEFT_POSITION 1 35 | #endif 36 | 37 | void overview_ui_init (OverviewPrefs *prefs); 38 | void overview_ui_deinit (void); 39 | GtkWidget *overview_ui_get_menu_item (void); 40 | void overview_ui_queue_update (void); 41 | 42 | #endif // OVERVIEWUI_H_ 43 | -------------------------------------------------------------------------------- /patches/geanyscihunting.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/document.c b/src/document.c 2 | index 8a57d93..edaed0d 100644 3 | --- a/src/document.c 4 | +++ b/src/document.c 5 | @@ -226,16 +226,8 @@ GeanyDocument *document_find_by_filename(const gchar *utf8_filename) 6 | /* returns the document which has sci, or NULL. */ 7 | GeanyDocument *document_find_by_sci(ScintillaObject *sci) 8 | { 9 | - guint i; 10 | - 11 | - g_return_val_if_fail(sci != NULL, NULL); 12 | - 13 | - for (i = 0; i < documents_array->len; i++) 14 | - { 15 | - if (documents[i]->is_valid && documents[i]->editor->sci == sci) 16 | - return documents[i]; 17 | - } 18 | - return NULL; 19 | + g_return_val_if_fail(IS_SCINTILLA(sci), NULL); 20 | + return g_object_get_data(G_OBJECT(sci), "geany-document"); 21 | } 22 | 23 | 24 | @@ -305,6 +297,16 @@ gint document_get_notebook_page(GeanyDocument *doc) 25 | } 26 | 27 | 28 | +/* Check if the object is not only a Scintilla but also has our special 29 | + * "geany-document" tag set in editor_create_widget(). This prevents finding 30 | + * other Scintilla widgets that plugin's might have sneakily packed into the 31 | + * widget tree we search through to find our Scintilla. */ 32 | +static inline gboolean is_geany_scintilla(gpointer obj) 33 | +{ 34 | + return IS_SCINTILLA(obj) && (g_object_get_data(obj, "geany-document") != NULL); 35 | +} 36 | + 37 | + 38 | /* 39 | * Recursively searches a containers children until it finds a 40 | * Scintilla widget, or NULL if one was not found. 41 | @@ -319,7 +321,7 @@ static ScintillaObject *locate_sci_in_container(GtkWidget *container) 42 | children = gtk_container_get_children(GTK_CONTAINER(container)); 43 | for (iter = children; iter != NULL; iter = g_list_next(iter)) 44 | { 45 | - if (IS_SCINTILLA(iter->data)) 46 | + if (is_geany_scintilla(iter->data)) 47 | { 48 | sci = SCINTILLA(iter->data); 49 | break; 50 | @@ -327,7 +329,7 @@ static ScintillaObject *locate_sci_in_container(GtkWidget *container) 51 | else if (GTK_IS_CONTAINER(iter->data)) 52 | { 53 | sci = locate_sci_in_container(iter->data); 54 | - if (IS_SCINTILLA(sci)) 55 | + if (is_geany_scintilla(sci)) 56 | break; 57 | sci = NULL; 58 | } 59 | diff --git a/src/editor.c b/src/editor.c 60 | index fc04ac6..c5c5ce3 100644 61 | --- a/src/editor.c 62 | +++ b/src/editor.c 63 | @@ -4849,6 +4849,9 @@ GeanyEditor *editor_create(GeanyDocument *doc) 64 | editor->line_breaking = FALSE; 65 | 66 | editor->sci = editor_create_widget(editor); 67 | + 68 | + g_object_set_data(G_OBJECT(editor->sci), "geany-document", doc); 69 | + 70 | return editor; 71 | } 72 | 73 | -------------------------------------------------------------------------------- /screenshots/Makefile.am: -------------------------------------------------------------------------------- 1 | screenshotdir = $(docdir)/screenshots 2 | dist_screenshot_DATA = \ 3 | screenshot-dark.png \ 4 | screenshot-keybindings.png \ 5 | screenshot-light.png \ 6 | screenshot-prefs.png \ 7 | screenshot-view-menu.png 8 | -------------------------------------------------------------------------------- /screenshots/screenshot-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/screenshots/screenshot-dark.png -------------------------------------------------------------------------------- /screenshots/screenshot-keybindings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/screenshots/screenshot-keybindings.png -------------------------------------------------------------------------------- /screenshots/screenshot-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/screenshots/screenshot-light.png -------------------------------------------------------------------------------- /screenshots/screenshot-prefs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/screenshots/screenshot-prefs.png -------------------------------------------------------------------------------- /screenshots/screenshot-view-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebrainz/overview-plugin/a024af1161c0b9c2455e458c974f253ef4beef4d/screenshots/screenshot-view-menu.png --------------------------------------------------------------------------------