comparison src/graphics.cc @ 11175:c0a95a5c6d25

Address the speed of plotting large hggroup groups and in particular contours (bug #31305). Changes to address this include - Use __go_patch__ in __contour__ rather than patch so that the cost of setting up the callback functions is avoided. The contourgroup callback handles the updating of properties. - Add children_property class to store children in a list so that adding and deleting children is a low cost operation. - Create a new version of update_axis_limits code that doesn't force the recalculation of all of the objects children. Patch also allows unclosed patch contours with the FLTK backend.
author David Bateman <dbateman@free.fr>
date Tue, 02 Nov 2010 00:47:31 +0100
parents 36442102c340
children 5fa7667f90e5
comparison
equal deleted inserted replaced
11174:2114867f2a50 11175:c0a95a5c6d25
686 686
687 for (octave_idx_type i = 0; i < n; i++) 687 for (octave_idx_type i = 0; i < n; i++)
688 { 688 {
689 double e = double (data[i]); 689 double e = double (data[i]);
690 690
691 if (! (xisinf (e) || xisnan (e))) 691 // Don't need to test for NaN here as NaN>x and NaN<x is always false
692 if (! xisinf (e))
692 { 693 {
693 if (e < emin) 694 if (e < emin)
694 emin = e; 695 emin = e;
695 696
696 if (e > emax) 697 if (e > emax)
1204 get_name ().c_str ()); 1205 get_name ().c_str ());
1205 1206
1206 return false; 1207 return false;
1207 } 1208 }
1208 1209
1210 Matrix
1211 children_property::do_get_children (bool return_hidden) const
1212 {
1213 Matrix retval (children_list.size (), 1);
1214 octave_idx_type k = 0;
1215
1216 graphics_object go = gh_manager::get_object (0);
1217
1218 root_figure::properties& props =
1219 dynamic_cast<root_figure::properties&> (go.get_properties ());
1220
1221 if (! props.is_showhiddenhandles ())
1222 {
1223 for (const_children_list_iterator p = children_list.begin ();
1224 p != children_list.end (); p++)
1225 {
1226 graphics_handle kid = *p;
1227
1228 if (gh_manager::is_handle_visible (kid))
1229 {
1230 if (! return_hidden)
1231 retval(k++) = *p;
1232 }
1233 else if (return_hidden)
1234 retval(k++) = *p;
1235 }
1236
1237 retval.resize (k, 1);
1238 }
1239 else
1240 {
1241 for (const_children_list_iterator p = children_list.begin ();
1242 p != children_list.end (); p++)
1243 retval(k++) = *p;
1244 }
1245
1246 return retval;
1247 }
1248
1249 void
1250 children_property::do_delete_children (bool clear)
1251 {
1252 for (children_list_iterator p = children_list.begin ();
1253 p != children_list.end (); p++)
1254 {
1255 graphics_object go = gh_manager::get_object (*p);
1256
1257 if (go.valid_object ())
1258 gh_manager::free (*p);
1259
1260 }
1261
1262 if (clear)
1263 children_list.clear ();
1264 }
1265
1209 bool 1266 bool
1210 callback_property::validate (const octave_value& v) const 1267 callback_property::validate (const octave_value& v) const
1211 { 1268 {
1212 // case 1: function handle 1269 // case 1: function handle
1213 // case 2: cell array with first element being a function handle 1270 // case 2: cell array with first element being a function handle
1881 graphics_object obj = gh_manager::get_object (h); 1938 graphics_object obj = gh_manager::get_object (h);
1882 obj.set (args); 1939 obj.set (args);
1883 } 1940 }
1884 } 1941 }
1885 1942
1886
1887 static octave_value 1943 static octave_value
1888 xget (const graphics_handle& h, const caseless_str& name) 1944 xget (const graphics_handle& h, const caseless_str& name)
1889 { 1945 {
1890 graphics_object obj = gh_manager::get_object (h); 1946 graphics_object obj = gh_manager::get_object (h);
1891 return obj.get (name); 1947 return obj.get (name);
1950 2006
1951 static void 2007 static void
1952 adopt (const graphics_handle& p, const graphics_handle& h) 2008 adopt (const graphics_handle& p, const graphics_handle& h)
1953 { 2009 {
1954 graphics_object parent_obj = gh_manager::get_object (p); 2010 graphics_object parent_obj = gh_manager::get_object (p);
1955
1956 parent_obj.adopt (h); 2011 parent_obj.adopt (h);
1957 } 2012 }
1958 2013
1959 static bool 2014 static bool
1960 is_handle (const graphics_handle& h) 2015 is_handle (const graphics_handle& h)
2145 else 2200 else
2146 return it->second; 2201 return it->second;
2147 } 2202 }
2148 2203
2149 void 2204 void
2150 base_properties::remove_child (const graphics_handle& h)
2151 {
2152 octave_idx_type k = -1;
2153 octave_idx_type n = children.numel ();
2154 for (octave_idx_type i = 0; i < n; i++)
2155 {
2156 if (h.value () == children(i))
2157 {
2158 k = i;
2159 break;
2160 }
2161 }
2162
2163 if (k >= 0)
2164 {
2165 Matrix new_kids (n-1, 1);
2166 octave_idx_type j = 0;
2167 for (octave_idx_type i = 0; i < n; i++)
2168 {
2169 if (i != k)
2170 new_kids(j++) = children(i);
2171 }
2172 children = new_kids;
2173 mark_modified ();
2174 }
2175 }
2176
2177 void
2178 base_properties::set_parent (const octave_value& val) 2205 base_properties::set_parent (const octave_value& val)
2179 { 2206 {
2180 double tmp = val.double_value (); 2207 double tmp = val.double_value ();
2181 2208
2182 graphics_handle new_parent = octave_NaN; 2209 graphics_handle new_parent = octave_NaN;
2198 else 2225 else
2199 error ("set: invalid graphics handle (= %g) for parent", tmp); 2226 error ("set: invalid graphics handle (= %g) for parent", tmp);
2200 } 2227 }
2201 else 2228 else
2202 error ("set: expecting parent to be a graphics handle"); 2229 error ("set: expecting parent to be a graphics handle");
2203 }
2204
2205 void
2206 base_properties::set_children (const octave_value& val)
2207 {
2208 const Matrix new_kids = val.matrix_value ();
2209
2210 octave_idx_type nel = new_kids.numel ();
2211
2212 const Matrix new_kids_column = new_kids.reshape (dim_vector (nel, 1));
2213
2214 bool ok = true;
2215
2216 if (! error_state)
2217 {
2218 const Matrix visible_kids = get_children ();
2219
2220 if (visible_kids.numel () == new_kids.numel ())
2221 {
2222 Matrix t1 = visible_kids.sort ();
2223 Matrix t2 = new_kids_column.sort ();
2224
2225 if (t1 != t2)
2226 ok = false;
2227 }
2228 else
2229 ok = false;
2230
2231 if (! ok)
2232 error ("set: new children must be a permutation of existing children");
2233 }
2234 else
2235 {
2236 ok = false;
2237 error ("set: expecting children to be array of graphics handles");
2238 }
2239
2240 if (ok)
2241 children = new_kids_column.stack (get_hidden_children ());
2242 } 2230 }
2243 2231
2244 void 2232 void
2245 base_properties::mark_modified (void) 2233 base_properties::mark_modified (void)
2246 { 2234 {
2267 if (obj) 2255 if (obj)
2268 obj.update_axis_limits (axis_type); 2256 obj.update_axis_limits (axis_type);
2269 } 2257 }
2270 2258
2271 void 2259 void
2272 base_properties::delete_children (void) 2260 base_properties::update_axis_limits (const std::string& axis_type,
2273 { 2261 const graphics_handle& h) const
2274 octave_idx_type n = children.numel (); 2262 {
2275 2263 graphics_object obj = gh_manager::get_object (__myhandle__);
2276 // A callback function might have already deleted the child, 2264
2277 // so check before deleting 2265 if (obj)
2278 for (octave_idx_type i = 0; i < n; i++) 2266 obj.update_axis_limits (axis_type, h);
2279 {
2280 graphics_object go = gh_manager::get_object (children(i));
2281
2282 if (go.valid_object ())
2283 gh_manager::free (children(i));
2284 }
2285 } 2267 }
2286 2268
2287 graphics_backend 2269 graphics_backend
2288 base_properties::get_backend (void) const 2270 base_properties::get_backend (void) const
2289 { 2271 {
2468 else 2450 else
2469 error ("base_graphics_object::update_axis_limits: invalid graphics object"); 2451 error ("base_graphics_object::update_axis_limits: invalid graphics object");
2470 } 2452 }
2471 2453
2472 void 2454 void
2455 base_graphics_object::update_axis_limits (const std::string& axis_type,
2456 const graphics_handle& h)
2457 {
2458 if (valid_object ())
2459 {
2460 graphics_object parent_obj = gh_manager::get_object (get_parent ());
2461
2462 if (parent_obj)
2463 parent_obj.update_axis_limits (axis_type, h);
2464 }
2465 else
2466 error ("base_graphics_object::update_axis_limits: invalid graphics object");
2467 }
2468
2469 void
2473 base_graphics_object::remove_all_listeners (void) 2470 base_graphics_object::remove_all_listeners (void)
2474 { 2471 {
2475 octave_map m = get (true).map_value (); 2472 octave_map m = get (true).map_value ();
2476 2473
2477 for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++) 2474 for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++)
2726 2723
2727 if (gh == currentaxes.handle_value ()) 2724 if (gh == currentaxes.handle_value ())
2728 { 2725 {
2729 graphics_handle new_currentaxes; 2726 graphics_handle new_currentaxes;
2730 2727
2731 for (octave_idx_type i = 0; i < children.numel (); i++) 2728 Matrix kids = get_children ();
2732 { 2729
2733 graphics_handle kid = children(i); 2730 for (octave_idx_type i = 0; i < kids.numel (); i++)
2731 {
2732 graphics_handle kid = kids(i);
2734 2733
2735 graphics_object go = gh_manager::get_object (kid); 2734 graphics_object go = gh_manager::get_object (kid);
2736 2735
2737 if (go.isa ("axes")) 2736 if (go.isa ("axes"))
2738 { 2737 {
3416 position = default_axes_position (); 3415 position = default_axes_position ();
3417 3416
3418 activepositionproperty = "outerposition"; 3417 activepositionproperty = "outerposition";
3419 } 3418 }
3420 3419
3421 delete_children (); 3420 delete_children (true);
3422
3423 children = Matrix ();
3424 3421
3425 xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, false); 3422 xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, false);
3426 ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, false); 3423 ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, false);
3427 zlabel = gh_manager::make_graphics_handle ("text", __myhandle__, false); 3424 zlabel = gh_manager::make_graphics_handle ("text", __myhandle__, false);
3428 title = gh_manager::make_graphics_handle ("text", __myhandle__, false); 3425 title = gh_manager::make_graphics_handle ("text", __myhandle__, false);
3500 delete_text_child (zlabel); 3497 delete_text_child (zlabel);
3501 else if (title.handle_value ().ok () && h == title.handle_value ()) 3498 else if (title.handle_value ().ok () && h == title.handle_value ())
3502 delete_text_child (title); 3499 delete_text_child (title);
3503 else 3500 else
3504 base_properties::remove_child (h); 3501 base_properties::remove_child (h);
3505 }
3506
3507 Matrix
3508 base_properties::get_children_internal (bool return_hidden) const
3509 {
3510 Matrix retval = children;
3511
3512 graphics_object go = gh_manager::get_object (0);
3513
3514 root_figure::properties& props =
3515 dynamic_cast<root_figure::properties&> (go.get_properties ());
3516
3517 if (! props.is_showhiddenhandles ())
3518 {
3519 octave_idx_type k = 0;
3520
3521 for (octave_idx_type i = 0; i < children.numel (); i++)
3522 {
3523 graphics_handle kid = children (i);
3524
3525 if (gh_manager::is_handle_visible (kid))
3526 {
3527 if (! return_hidden)
3528 retval(k++) = children(i);
3529 }
3530 else
3531 {
3532 if (return_hidden)
3533 retval(k++) = children(i);
3534 }
3535 }
3536
3537 retval.resize (k, 1);
3538 }
3539
3540 return retval;
3541 }
3542
3543 Matrix
3544 base_properties::get_children (void) const
3545 {
3546 return get_children_internal (false);
3547 }
3548
3549 Matrix
3550 base_properties::get_hidden_children (void) const
3551 {
3552 return get_children_internal (true);
3553 } 3502 }
3554 3503
3555 inline Matrix 3504 inline Matrix
3556 xform_matrix (void) 3505 xform_matrix (void)
3557 { 3506 {
4551 break; 4500 break;
4552 } 4501 }
4553 } 4502 }
4554 4503
4555 static bool updating_axis_limits = false; 4504 static bool updating_axis_limits = false;
4505
4506 void
4507 axes::update_axis_limits (const std::string& axis_type,
4508 const graphics_handle& h)
4509 {
4510 if (updating_axis_limits)
4511 return;
4512
4513 Matrix kids = Matrix (1, 1, h.value ());
4514
4515 double min_val = octave_Inf;
4516 double max_val = -octave_Inf;
4517 double min_pos = octave_Inf;
4518
4519 char update_type = 0;
4520
4521 Matrix limits;
4522 double val;
4523
4524 #define FIX_LIMITS \
4525 if (limits.numel() == 3) \
4526 { \
4527 val = limits(0); \
4528 if (! (xisinf (val) || xisnan (val))) \
4529 min_val = val; \
4530 val = limits(1); \
4531 if (! (xisinf (val) || xisnan (val))) \
4532 max_val = val; \
4533 val = limits(2); \
4534 if (! (xisinf (val) || xisnan (val))) \
4535 min_pos = val; \
4536 } \
4537 else \
4538 { \
4539 limits.resize(3, 1); \
4540 limits(0) = min_val; \
4541 limits(1) = max_val; \
4542 limits(2) = min_pos; \
4543 }
4544
4545 if (axis_type == "xdata" || axis_type == "xscale"
4546 || axis_type == "xlimmode" || axis_type == "xliminclude"
4547 || axis_type == "xlim")
4548 {
4549 if (xproperties.xlimmode_is ("auto"))
4550 {
4551 limits = xproperties.get_xlim ().matrix_value ();
4552 FIX_LIMITS ;
4553
4554 get_children_limits (min_val, max_val, min_pos, kids, 'x');
4555
4556 limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
4557 xproperties.xscale_is ("log"));
4558
4559 update_type = 'x';
4560 }
4561 }
4562 else if (axis_type == "ydata" || axis_type == "yscale"
4563 || axis_type == "ylimmode" || axis_type == "yliminclude"
4564 || axis_type == "ylim")
4565 {
4566 if (xproperties.ylimmode_is ("auto"))
4567 {
4568 limits = xproperties.get_ylim ().matrix_value ();
4569 FIX_LIMITS ;
4570
4571 get_children_limits (min_val, max_val, min_pos, kids, 'y');
4572
4573 limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
4574 xproperties.yscale_is ("log"));
4575
4576 update_type = 'y';
4577 }
4578 }
4579 else if (axis_type == "zdata" || axis_type == "zscale"
4580 || axis_type == "zlimmode" || axis_type == "zliminclude"
4581 || axis_type == "zlim")
4582 {
4583 if (xproperties.zlimmode_is ("auto"))
4584 {
4585 limits = xproperties.get_zlim ().matrix_value ();
4586 FIX_LIMITS ;
4587
4588 get_children_limits (min_val, max_val, min_pos, kids, 'z');
4589
4590 limits = xproperties.get_axis_limits (min_val, max_val, min_pos,
4591 xproperties.zscale_is ("log"));
4592
4593 update_type = 'z';
4594 }
4595 }
4596 else if (axis_type == "cdata" || axis_type == "climmode"
4597 || axis_type == "cdatamapping" || axis_type == "climinclude"
4598 || axis_type == "clim")
4599 {
4600 if (xproperties.climmode_is ("auto"))
4601 {
4602 limits = xproperties.get_clim ().matrix_value ();
4603 FIX_LIMITS ;
4604
4605 get_children_limits (min_val, max_val, min_pos, kids, 'c');
4606
4607 if (min_val > max_val)
4608 {
4609 min_val = min_pos = 0;
4610 max_val = 1;
4611 }
4612 else if (min_val == max_val)
4613 max_val = min_val + 1;
4614
4615 limits.resize (1, 2);
4616
4617 limits(0) = min_val;
4618 limits(1) = max_val;
4619
4620 update_type = 'c';
4621 }
4622
4623 }
4624 else if (axis_type == "alphadata" || axis_type == "alimmode"
4625 || axis_type == "alphadatamapping" || axis_type == "aliminclude"
4626 || axis_type == "alim")
4627 {
4628 if (xproperties.alimmode_is ("auto"))
4629 {
4630 limits = xproperties.get_alim ().matrix_value ();
4631 FIX_LIMITS ;
4632
4633 get_children_limits (min_val, max_val, min_pos, kids, 'a');
4634
4635 if (min_val > max_val)
4636 {
4637 min_val = min_pos = 0;
4638 max_val = 1;
4639 }
4640 else if (min_val == max_val)
4641 max_val = min_val + 1;
4642
4643 limits.resize (1, 2);
4644
4645 limits(0) = min_val;
4646 limits(1) = max_val;
4647
4648 update_type = 'a';
4649 }
4650
4651 }
4652
4653 #undef FIX_LIMITS
4654
4655 unwind_protect frame;
4656 frame.protect_var (updating_axis_limits);
4657
4658 updating_axis_limits = true;
4659
4660 switch (update_type)
4661 {
4662 case 'x':
4663 xproperties.set_xlim (limits);
4664 xproperties.set_xlimmode ("auto");
4665 xproperties.update_xlim ();
4666 break;
4667
4668 case 'y':
4669 xproperties.set_ylim (limits);
4670 xproperties.set_ylimmode ("auto");
4671 xproperties.update_ylim ();
4672 break;
4673
4674 case 'z':
4675 xproperties.set_zlim (limits);
4676 xproperties.set_zlimmode ("auto");
4677 xproperties.update_zlim ();
4678 break;
4679
4680 case 'c':
4681 xproperties.set_clim (limits);
4682 xproperties.set_climmode ("auto");
4683 break;
4684
4685 case 'a':
4686 xproperties.set_alim (limits);
4687 xproperties.set_alimmode ("auto");
4688 break;
4689
4690 default:
4691 break;
4692 }
4693
4694 xproperties.update_transform ();
4695
4696 }
4556 4697
4557 void 4698 void
4558 axes::update_axis_limits (const std::string& axis_type) 4699 axes::update_axis_limits (const std::string& axis_type)
4559 { 4700 {
4560 if (updating_axis_limits || updating_aspectratios) 4701 if (updating_axis_limits || updating_aspectratios)
5067 } 5208 }
5068 } 5209 }
5069 5210
5070 // --------------------------------------------------------------------- 5211 // ---------------------------------------------------------------------
5071 5212
5072 void 5213 void
5073 hggroup::update_axis_limits (const std::string& axis_type) 5214 hggroup::properties::update_limits (void) const
5074 { 5215 {
5075 Matrix kids = xproperties.get_children (); 5216 graphics_object obj = gh_manager::get_object (__myhandle__);
5076 5217
5218 if (obj)
5219 {
5220 obj.update_axis_limits ("xlim");
5221 obj.update_axis_limits ("ylim");
5222 obj.update_axis_limits ("zlim");
5223 obj.update_axis_limits ("clim");
5224 obj.update_axis_limits ("alim");
5225 }
5226 }
5227
5228 void
5229 hggroup::properties::update_limits (const graphics_handle& h) const
5230 {
5231 graphics_object obj = gh_manager::get_object (__myhandle__);
5232
5233 if (obj)
5234 {
5235 obj.update_axis_limits ("xlim", h);
5236 obj.update_axis_limits ("ylim", h);
5237 obj.update_axis_limits ("zlim", h);
5238 obj.update_axis_limits ("clim", h);
5239 obj.update_axis_limits ("alim", h);
5240 }
5241 }
5242
5243 static bool updating_hggroup_limits = false;
5244
5245 void
5246 hggroup::update_axis_limits (const std::string& axis_type,
5247 const graphics_handle& h)
5248 {
5249 if (updating_hggroup_limits)
5250 return;
5251
5252 Matrix kids = Matrix (1, 1, h.value ());
5253
5077 double min_val = octave_Inf; 5254 double min_val = octave_Inf;
5078 double max_val = -octave_Inf; 5255 double max_val = -octave_Inf;
5079 double min_pos = octave_Inf; 5256 double min_pos = octave_Inf;
5080 5257
5258 Matrix limits;
5259 double val;
5260
5081 char update_type = 0; 5261 char update_type = 0;
5082 5262
5083 if (axis_type == "xlim" || axis_type == "xliminclude") 5263 if (axis_type == "xlim" || axis_type == "xliminclude")
5084 { 5264 {
5265 limits = xproperties.get_xlim ().matrix_value ();
5266 update_type = 'x';
5267 }
5268 else if (axis_type == "ylim" || axis_type == "yliminclude")
5269 {
5270 limits = xproperties.get_ylim ().matrix_value ();
5271 update_type = 'y';
5272 }
5273 else if (axis_type == "zlim" || axis_type == "zliminclude")
5274 {
5275 limits = xproperties.get_zlim ().matrix_value ();
5276 update_type = 'z';
5277 }
5278 else if (axis_type == "clim" || axis_type == "climinclude")
5279 {
5280 limits = xproperties.get_clim ().matrix_value ();
5281 update_type = 'c';
5282 }
5283 else if (axis_type == "alim" || axis_type == "aliminclude")
5284 {
5285 limits = xproperties.get_alim ().matrix_value ();
5286 update_type = 'a';
5287 }
5288
5289 if (limits.numel() == 3)
5290 {
5291 val = limits(0);
5292 if (! (xisinf (val) || xisnan (val)))
5293 min_val = val;
5294 val = limits(1);
5295 if (! (xisinf (val) || xisnan (val)))
5296 max_val = val;
5297 val = limits(2);
5298 if (! (xisinf (val) || xisnan (val)))
5299 min_pos = val;
5300 }
5301 else
5302 {
5303 limits.resize(3,1);
5304 limits(0) = min_val;
5305 limits(1) = max_val;
5306 limits(2) = min_pos;
5307 }
5308
5309 get_children_limits (min_val, max_val, min_pos, kids, update_type);
5310
5311 unwind_protect frame;
5312 frame.protect_var (updating_hggroup_limits);
5313
5314 updating_hggroup_limits = true;
5315
5316 if (limits(0) != min_val || limits(1) != max_val || limits(2) != min_pos)
5317 {
5318 limits(0) = min_val;
5319 limits(1) = max_val;
5320 limits(2) = min_pos;
5321
5322 switch (update_type)
5323 {
5324 case 'x':
5325 xproperties.set_xlim (limits);
5326 break;
5327
5328 case 'y':
5329 xproperties.set_ylim (limits);
5330 break;
5331
5332 case 'z':
5333 xproperties.set_zlim (limits);
5334 break;
5335
5336 case 'c':
5337 xproperties.set_clim (limits);
5338 break;
5339
5340 case 'a':
5341 xproperties.set_alim (limits);
5342 break;
5343
5344 default:
5345 break;
5346 }
5347
5348 base_graphics_object::update_axis_limits (axis_type, h);
5349 }
5350 }
5351
5352 void
5353 hggroup::update_axis_limits (const std::string& axis_type)
5354 {
5355 if (updating_hggroup_limits)
5356 return;
5357
5358 Matrix kids = xproperties.get_children ();
5359
5360 double min_val = octave_Inf;
5361 double max_val = -octave_Inf;
5362 double min_pos = octave_Inf;
5363
5364 char update_type = 0;
5365
5366 if (axis_type == "xlim" || axis_type == "xliminclude")
5367 {
5085 get_children_limits (min_val, max_val, min_pos, kids, 'x'); 5368 get_children_limits (min_val, max_val, min_pos, kids, 'x');
5086 5369
5087 update_type = 'x'; 5370 update_type = 'x';
5088 } 5371 }
5089 else if (axis_type == "ylim" || axis_type == "yliminclude") 5372 else if (axis_type == "ylim" || axis_type == "yliminclude")
5090 { 5373 {
5091 get_children_limits (min_val, max_val, min_pos, kids, 'y'); 5374 get_children_limits (min_val, max_val, min_pos, kids, 'y');
5101 else if (axis_type == "clim" || axis_type == "climinclude") 5384 else if (axis_type == "clim" || axis_type == "climinclude")
5102 { 5385 {
5103 get_children_limits (min_val, max_val, min_pos, kids, 'c'); 5386 get_children_limits (min_val, max_val, min_pos, kids, 'c');
5104 5387
5105 update_type = 'c'; 5388 update_type = 'c';
5106
5107 } 5389 }
5108 else if (axis_type == "alim" || axis_type == "aliminclude") 5390 else if (axis_type == "alim" || axis_type == "aliminclude")
5109 { 5391 {
5110 get_children_limits (min_val, max_val, min_pos, kids, 'a'); 5392 get_children_limits (min_val, max_val, min_pos, kids, 'a');
5111 5393
5112 update_type = 'a'; 5394 update_type = 'a';
5113 } 5395 }
5396
5397 unwind_protect frame;
5398 frame.protect_var (updating_hggroup_limits);
5399
5400 updating_hggroup_limits = true;
5114 5401
5115 Matrix limits (1, 3, 0.0); 5402 Matrix limits (1, 3, 0.0);
5116 5403
5117 limits(0) = min_val; 5404 limits(0) = min_val;
5118 limits(1) = max_val; 5405 limits(1) = max_val;