PageRenderTime 197ms CodeModel.GetById 68ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/BufferTabs/buffertabs/ColorTabs.java

#
Java | 401 lines | 246 code | 58 blank | 97 comment | 20 complexity | 0cfdfff28cf2fcd7eda210e65e22a200 MD5 | raw file
  1/*
  2*  ColorTabs.java - Part of the BufferTabs plugin for jEdit.
  3*  Copyright (C) 2003 Chris Samuels
  4* :tabSize=8:indentSize=8:noTabs=false:
  5* :folding=explicit:collapseFolds=1:
  6*
  7*  This program is free software; you can redistribute it and/or
  8*  modify it under the terms of the GNU General Public License
  9*  as published by the Free Software Foundation; either version 2
 10*  of the License, or 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 20*/
 21
 22
 23package buffertabs;
 24
 25//{{{ Imports
 26import java.awt.Color;
 27import java.util.Map;
 28import java.util.HashMap;
 29import java.util.Random;
 30import java.util.List;
 31import java.util.ArrayList;
 32import java.util.regex.Pattern;
 33import java.util.regex.PatternSyntaxException;
 34
 35import org.gjt.sp.jedit.jEdit;
 36
 37import org.gjt.sp.util.Log;
 38import org.gjt.sp.util.StandardUtilities;
 39//}}}
 40
 41
 42/**
 43*  An add-on to BufferTabs to allow colored backgrounds on tabs
 44*
 45* @author     Chris Samuels
 46* @created    24 February 2003
 47*/
 48public class ColorTabs
 49{
 50	private static final int JND = 4;
 51	
 52	private static final int DARKEN_LOWEST_COLOR = 0;
 53	private static final int DARKEN_HIGHEST_COLOR = 150;
 54	private static final int DARKEN_RANGE = DARKEN_HIGHEST_COLOR - DARKEN_LOWEST_COLOR;
 55	private static final float DARKEN_RATIO = ((float) DARKEN_RANGE / 254);
 56	
 57	private static final int MUTE_LOWEST_COLOR = 150;
 58	private static final int MUTE_HIGHEST_COLOR = 230;
 59	private static final int MUTE_RANGE = MUTE_HIGHEST_COLOR - MUTE_LOWEST_COLOR;
 60	private static final float MUTE_RATIO = ((float) MUTE_RANGE / 254);
 61	
 62	private static ColorTabs colorTabs = null;
 63	
 64	private boolean enabled             = false;
 65	private boolean selectedColorized   = true;
 66	private boolean selectedForegroundColorized = false;
 67	private boolean foregroundColorized = false;
 68	private boolean muteColors          = true;
 69	private boolean colorVariation      = true;
 70	
 71	private List<ColorEntry> colors;
 72	private final Map<String,Color> colorsAssigned = new HashMap<String,Color>();
 73	private final Object lock = new Object();
 74	private Random rnd = null;
 75	
 76	
 77	//{{{ ColorTabs constructor
 78	/**
 79	 *  Singleton class
 80	 */
 81	private ColorTabs() { }
 82	//}}}
 83	
 84	//{{{ isEnabled() method
 85	public boolean isEnabled() 
 86	{
 87		return this.enabled;
 88	} //}}}
 89
 90	//{{{ setEnabled() method
 91	public void setEnabled(boolean enabled)
 92	{
 93		this.enabled = enabled;
 94	} //}}}
 95	
 96	//{{{ isSelectedColorized() method
 97	public boolean isSelectedColorized()
 98	{
 99		return this.selectedColorized;
100	} //}}}
101
102	//{{{ setSelectedColorized() method
103	public void setSelectedColorized(boolean selectedColorized) 
104	{
105		this.selectedColorized = selectedColorized;
106	} //}}}
107
108	//{{{ isForegroundColorized() method
109	public boolean isForegroundColorized() 
110	{
111		return this.foregroundColorized;
112	} //}}}
113
114	//{{{ isSelectedForegroundColorized() method
115	public boolean isSelectedForegroundColorized() 
116	{
117		return this.selectedForegroundColorized;
118	} //}}}
119	
120	//{{{ setForegroundColorized() method
121	public void setForegroundColorized(boolean foregroundColorized) 
122	{
123		this.foregroundColorized = foregroundColorized;
124	} //}}}
125	
126	//{{{ setSelectedForegroundColorized() method
127	public void setSelectedForegroundColorized(boolean foregroundColorized) 
128	{
129		this.selectedForegroundColorized = foregroundColorized;
130	} //}}}
131	
132	//{{{ hasMuteColors() method
133	public boolean hasMuteColors() 
134	{
135		return this.muteColors;
136	} //}}}
137	
138	//{{{ setMuteColors() method
139	public void setMuteColors(boolean muteColors) 
140	{
141		this.muteColors = muteColors;
142	} //}}}
143	
144	//{{{ hasColorVariation() method
145	public boolean hasColorVariation() 
146	{
147		return this.colorVariation;
148	} //}}}
149
150	//{{{ setColorVariation() method
151	public void setColorVariation(boolean colorVariation) 
152	{
153		this.colorVariation = colorVariation;
154	} //}}}
155	
156	//{{{ alterColorDarken() method
157	/**
158	 *  Creates colors suitable for reading text labels. Uniformly moves the
159	 *  color range to a darker range.
160	 *
161	 * @param  color
162	 * @return
163	 */
164	Color alterColorDarken(Color color)
165	{
166		if (color == null)
167		{
168			return Color.black;
169		}
170		
171		int r = color.getRed();
172		int g = color.getGreen();
173		int b = color.getBlue();
174		
175		r = (int) (DARKEN_HIGHEST_COLOR - (r * DARKEN_RATIO));
176		g = (int) (DARKEN_HIGHEST_COLOR - (g * DARKEN_RATIO));
177		b = (int) (DARKEN_HIGHEST_COLOR - (b * DARKEN_RATIO));
178		
179		if (this.hasColorVariation())
180		{
181			r -= rnd.nextInt(5) * JND;
182			g -= rnd.nextInt(5) * JND;
183			b -= rnd.nextInt(5) * JND;
184			r = r / JND * JND;
185			g = g / JND * JND;
186			b = b / JND * JND;
187		}
188		
189		r = Math.max(DARKEN_LOWEST_COLOR, Math.min(r, DARKEN_HIGHEST_COLOR));
190		g = Math.max(DARKEN_LOWEST_COLOR, Math.min(g, DARKEN_HIGHEST_COLOR));
191		b = Math.max(DARKEN_LOWEST_COLOR, Math.min(b, DARKEN_HIGHEST_COLOR));
192		
193		return new Color(r, g, b);
194	} //}}}
195	
196	//{{{ alterColorHighlight() method
197	/**
198	 *  Creates colors suitable for highlighting an active tab. Boosts the
199	 *  brightness and lowers saturation to achieve this.
200	 *
201	 * @param  color
202	 * @return
203	 */
204	Color alterColorHighlight(Color color)
205	{
206		if (color == null)
207		{
208			return Color.lightGray;
209		}
210		int r = color.getRed();
211		int g = color.getGreen();
212		int b = color.getBlue();
213		
214		float[] hsb = Color.RGBtoHSB(r, g, b, null);
215		
216		float s = hsb[1];
217		float v = hsb[2];
218		
219		s *= 0.6;
220		s = Math.max(0.0f, Math.min(s, 1f));
221		
222		v *= 1.6;
223		v = Math.max(0.0f, Math.min(v, 0.8f));
224		
225		return Color.getHSBColor(hsb[0], s, v);
226	} //}}}
227	
228	//{{{ alterColorMute() method
229	/**
230	 *  Creates colors suitable for backgrounds. Uniformly moves the color
231	 *  range to a lighter paler range.
232	 *
233	 *@param  color
234	 *@return
235	 */
236	Color alterColorMute(Color color)
237	{
238		if (color == null)
239		{
240			return Color.gray;
241		}
242		
243		int r = color.getRed();
244		int g = color.getGreen();
245		int b = color.getBlue();
246		
247		r = (int) (MUTE_LOWEST_COLOR + (r * MUTE_RATIO));
248		g = (int) (MUTE_LOWEST_COLOR + (g * MUTE_RATIO));
249		b = (int) (MUTE_LOWEST_COLOR + (b * MUTE_RATIO));
250		
251		if (this.hasColorVariation())
252		{
253			r += rnd.nextInt(5) * JND;
254			g += rnd.nextInt(5) * JND;
255			b += rnd.nextInt(5) * JND;
256			r = r / JND * JND;
257			g = g / JND * JND;
258			b = b / JND * JND;
259		}
260		
261		r = Math.max(MUTE_LOWEST_COLOR, Math.min(r, MUTE_HIGHEST_COLOR));
262		g = Math.max(MUTE_LOWEST_COLOR, Math.min(g, MUTE_HIGHEST_COLOR));
263		b = Math.max(MUTE_LOWEST_COLOR, Math.min(b, MUTE_HIGHEST_COLOR));
264		
265		return new Color(r, g, b);
266	} //}}}
267	
268	//{{{ getDefaultColorFor() method
269	/**
270	 *  Gets the defaultColorFor attribute of the ColorTabs class
271	 *
272	 * @param  name
273	 * @return       The defaultColorFor value
274	 */
275	public Color getDefaultColorFor(String name)
276	{
277		synchronized (lock)
278		{
279			if (colors == null)
280			{
281				loadColors();
282			}
283			
284			if (colorsAssigned.containsKey(name))
285			{
286				return colorsAssigned.get(name);
287			}
288			
289			for (int i = 0; i < colors.size(); i++)
290			{
291				ColorEntry entry = colors.get(i);
292				if (entry.re.matcher(name).matches())
293				{
294					Color newColor = null;
295					if (this.hasMuteColors())
296					{
297						if (this.isForegroundColorized())
298						{
299							newColor = alterColorDarken(entry.color);
300						}
301						else
302						{
303							newColor = alterColorMute(entry.color);
304						}
305					}
306					else
307					{
308						newColor = entry.color;
309					}
310					
311					colorsAssigned.put(name, newColor);
312					return newColor;
313				}
314			}
315			
316			return null;
317		}
318	} //}}}
319	
320	//{{{ instance() method
321	/**
322	 * Returns access to the Singleton ColorTabs class
323	 *
324	 * @return    Singleton ColorTabs
325	 */
326	public static ColorTabs instance()
327	{
328		if (colorTabs == null)
329		{
330			colorTabs = new ColorTabs();
331		}
332		return colorTabs;
333	} //}}}
334	
335	//{{{ loadColors() method
336	/**
337	 *  Load the colors from 'File system browser' color options
338	 */
339	private void loadColors()
340	{
341		synchronized (lock)
342		{
343			colors = new ArrayList<ColorEntry>();
344			
345			if (!jEdit.getBooleanProperty("vfs.browser.colorize"))
346			{
347				return;
348			}
349			
350			String glob;
351			int i = 0;
352			while ((glob = jEdit.getProperty("vfs.browser.colors." + i + ".glob")) != null)
353			{
354				try
355				{
356					colors.add(new ColorEntry(
357								  Pattern.compile(StandardUtilities.globToRE(glob)),
358								  jEdit.getColorProperty("vfs.browser.colors." + i + ".color",
359											 Color.black)));
360					i++;
361				}
362				catch (PatternSyntaxException e)
363				{
364					Log.log(Log.ERROR, ColorTabs.class, "Invalid regular expression: " + glob);
365					//Log.log( Log.ERROR, ColorTabs.class, e );
366					//Log.flushStream();
367				}
368			}
369		}
370	} //}}}
371	
372	//{{{ propertiesChanged() method
373	public void propertiesChanged()
374	{
375		loadColors();
376		colorsAssigned.clear();
377		//Set seed so color variation are 'mostly' consistent during a session
378		rnd = new java.util.Random(20020212);
379	} //}}}
380	
381	//{{{ ColorEntry class
382	/**
383	 * Class to store color match data
384	 *
385	 * @author     Chris Samuels
386	 * @created    24 February 2003
387	 */
388	static class ColorEntry
389	{
390		Color color;
391		Pattern re;
392		
393		
394		ColorEntry(Pattern re, Color color)
395		{
396			this.re = re;
397			this.color = color;
398		}
399	} //}}}
400}
401