]> Pileus Git - ~andy/gtk/blob - gtk/gtksizerequestcache.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtksizerequestcache.c
1 /* gtksizerequest.c
2  * Copyright (C) 2007-2010 Openismus GmbH
3  *
4  * Authors:
5  *      Mathias Hasselmann <mathias@openismus.com>
6  *      Tristan Van Berkom <tristan.van.berkom@gmail.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23
24 #include "gtksizerequestcacheprivate.h"
25
26 #include <string.h>
27
28 void
29 _gtk_size_request_cache_init (SizeRequestCache *cache)
30 {
31   memset (cache, 0, sizeof (SizeRequestCache));
32 }
33
34 static void
35 free_sizes (SizeRequest **sizes)
36 {
37   gint i;
38
39   for (i = 0; i < GTK_SIZE_REQUEST_CACHED_SIZES && sizes[i] != NULL; i++)
40     g_slice_free (SizeRequest, sizes[i]);
41       
42   g_slice_free1 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES, sizes);
43 }
44
45 void
46 _gtk_size_request_cache_free (SizeRequestCache *cache)
47 {
48   guint i;
49
50   for (i = 0; i < 2; i++)
51     {
52       if (cache->requests[i])
53         free_sizes (cache->requests[i]);
54     }
55 }
56
57 void
58 _gtk_size_request_cache_clear (SizeRequestCache *cache)
59                                
60 {
61   _gtk_size_request_cache_free (cache);
62   _gtk_size_request_cache_init (cache);
63 }
64
65 void
66 _gtk_size_request_cache_commit (SizeRequestCache *cache,
67                                 GtkOrientation    orientation,
68                                 gint              for_size,
69                                 gint              minimum_size,
70                                 gint              natural_size)
71 {
72   SizeRequest **cached_sizes;
73   SizeRequest  *cached_size;
74   guint         i, n_sizes;
75
76   /* First handle caching of the base requests */
77   if (for_size < 0)
78     {
79       cache->cached_size[orientation].minimum_size = minimum_size;
80       cache->cached_size[orientation].natural_size = natural_size;
81       cache->flags[orientation].cached_size_valid = TRUE;
82       return;
83     }
84
85   /* Check if the minimum_size and natural_size is already
86    * in the cache and if this result can be used to extend
87    * that cache entry 
88    */
89   cached_sizes = cache->requests[orientation];
90   n_sizes = cache->flags[orientation].n_cached_requests;
91
92   for (i = 0; i < n_sizes; i++)
93     {
94       if (cached_sizes[i]->cached_size.minimum_size == minimum_size &&
95           cached_sizes[i]->cached_size.natural_size == natural_size)
96         {
97           cached_sizes[i]->lower_for_size = MIN (cached_sizes[i]->lower_for_size, for_size);
98           cached_sizes[i]->upper_for_size = MAX (cached_sizes[i]->upper_for_size, for_size);
99           return;
100         }
101     }
102
103   /* If not found, pull a new size from the cache, the returned size cache
104    * will immediately be used to cache the new computed size so we go ahead
105    * and increment the last_cached_request right away */
106   if (n_sizes < GTK_SIZE_REQUEST_CACHED_SIZES)
107     {
108       cache->flags[orientation].n_cached_requests++;
109       cache->flags[orientation].last_cached_request = cache->flags[orientation].n_cached_requests - 1;
110     }
111   else
112     {
113       if (++cache->flags[orientation].last_cached_request == GTK_SIZE_REQUEST_CACHED_SIZES)
114         cache->flags[orientation].last_cached_request = 0;
115     }
116
117   if (cache->requests[orientation] == NULL)
118     cache->requests[orientation] = g_slice_alloc0 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES);
119
120   if (cache->requests[orientation][cache->flags[orientation].last_cached_request] == NULL)
121     cache->requests[orientation][cache->flags[orientation].last_cached_request] = g_slice_new (SizeRequest);
122
123   cached_size = cache->requests[orientation][cache->flags[orientation].last_cached_request];
124   cached_size->lower_for_size = for_size;
125   cached_size->upper_for_size = for_size;
126   cached_size->cached_size.minimum_size = minimum_size;
127   cached_size->cached_size.natural_size = natural_size;
128 }
129
130 /* looks for a cached size request for this for_size.
131  *
132  * Note that this caching code was originally derived from
133  * the Clutter toolkit but has evolved for other GTK+ requirements.
134  */
135 gboolean
136 _gtk_size_request_cache_lookup (SizeRequestCache *cache,
137                                 GtkOrientation    orientation,
138                                 gint              for_size,
139                                 gint             *minimum,
140                                 gint             *natural)
141 {
142   CachedSize *result = NULL;
143
144   if (for_size < 0)
145     {
146       if (cache->flags[orientation].cached_size_valid)
147         result = &cache->cached_size[orientation];
148     }
149   else
150     {
151       guint i;
152
153       /* Search for an already cached size */
154       for (i = 0; i < cache->flags[orientation].n_cached_requests; i++)
155         {
156           SizeRequest *cur = cache->requests[orientation][i];
157
158           if (cur->lower_for_size <= for_size &&
159               cur->upper_for_size >= for_size)
160             {
161               result = &cur->cached_size;
162               break;
163             }
164         }
165     }
166
167   if (result)
168     {
169       *minimum = result->minimum_size;
170       *natural = result->natural_size;
171       return TRUE;
172     }
173   else
174     return FALSE;
175 }
176