From 4e3f1848eeb28a78d71c6ffbda31279cee3fc5ea Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 15 Apr 2025 19:36:10 +0000 Subject: [PATCH] 8353000: Open source several swing tests batch2 Reviewed-by: azvegint --- .../JavaLAFMenuAcceleratorDelimiter.java | 83 +++++++ .../metal/MetalIconFactory/bug4952462.java | 98 ++++++++ .../MetalSliderUI/4186347/bug4186347.java | 74 ++++++ .../plaf/metal/MetalSliderUI/4186347/duke.gif | Bin 0 -> 1617 bytes .../metal/OceanTheme/4969419/bug4969419.java | 229 ++++++++++++++++++ .../plaf/metal/OceanTheme/4969419/duke.gif | Bin 0 -> 1929 bytes 6 files changed, 484 insertions(+) create mode 100644 test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java create mode 100644 test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java create mode 100644 test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java create mode 100644 test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif create mode 100644 test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java create mode 100644 test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif diff --git a/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java b/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java new file mode 100644 index 00000000000..f9885c98570 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/MenuItemUI/JavaLAFMenuAcceleratorDelimiter.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4210461 + * @summary Confirm Metal Look & Feel's MenuItem Accelerator Delimiter + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual JavaLAFMenuAcceleratorDelimiter + */ + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.KeyStroke; +import javax.swing.UIManager; + +public class JavaLAFMenuAcceleratorDelimiter { + static final String INSTRUCTIONS = """ + A simple check. The visual design specification for JLF/Metal asks for + a "-" to delimit the other two entities in a menu item's accelerator. + The test passes if the delimiter for the accelerator is correct when + opening the example menu. Otherwise, the test fails. + """; + + public static void main(String[] args) throws Exception { + // Set Metal L&F + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("JavaLAFMenuAcceleratorDelimiter Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(JavaLAFMenuAcceleratorDelimiter::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal L&F Accelerator Delimiter Test"); + JPanel menuPanel = new JPanel(); + JMenuBar menuBar = new JMenuBar(); + menuBar.setOpaque(true); + JMenu exampleMenu = new JMenu("Example"); + JMenuItem hiMenuItem = new JMenuItem("Hi There!"); + hiMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, + ActionEvent.CTRL_MASK)); + exampleMenu.add(hiMenuItem); + menuBar.add(exampleMenu); + menuPanel.add(menuBar); + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(menuPanel, BorderLayout.CENTER); + frame.setSize(250, 150); + return frame; + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java new file mode 100644 index 00000000000..f3562108314 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/MetalIconFactory/bug4952462.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4952462 + * @summary Ocean: Tests that disabled selected JRadioButton dot is NOT + * painted with the foreground color + * @modules java.desktop/sun.awt + * @library /test/lib + * @key headful + * @run main bug4952462 + */ + +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JRadioButton; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalTheme; + +import jtreg.SkippedException; +import sun.awt.AppContext; + +public class bug4952462 { + private static JFrame frame; + private static JRadioButton rb; + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + MetalTheme theme = (MetalTheme) AppContext.getAppContext().get("currentMetalTheme"); + if (theme == null || !"Ocean".equals(theme.getName())) { + throw new SkippedException("Current theme is not Ocean. Test is " + + "only for Metal's Ocean theme. Skipping test."); + } else { + Robot r = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Metal JRadioButton Foreground Color Test"); + frame.getContentPane().setLayout(new FlowLayout()); + rb = new JRadioButton("RadioButton", true); + rb.setEnabled(false); + rb.setForeground(Color.RED); + frame.getContentPane().add(rb); + frame.setSize(250, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + r.waitForIdle(); + r.delay(500); + + SwingUtilities.invokeAndWait(() -> { + Point p = rb.getLocationOnScreen(); + for (int i = 0; i < 50; i++) { + Color c = r.getPixelColor(p.x + 10 + i, p.y + (rb.getHeight() / 2)); + System.out.println(c); + if (c.getRed() > 200 && c.getBlue() < 200 && c.getGreen() < 200) { + throw new RuntimeException("Test failed. Radiobutton is red " + + "and not grey."); + } + } + }); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java b/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java new file mode 100644 index 00000000000..9de9d851805 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/bug4186347.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4186347 + * @summary Tests changing Slider.horizontalThumbIcon UIResource + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4186347 + */ + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JFrame; +import javax.swing.JSlider; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.IconUIResource; + +public class bug4186347 { + static final String INSTRUCTIONS = """ + If the slider's thumb icon is painted correctly + (that is centered vertically relative to slider + channel) then test passed, otherwise it failed. + """; + + public static void main(String[] args) throws Exception { + // Set Metal L&F + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4186347 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4186347::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal JSlider Icon Test"); + String a = System.getProperty("test.src", ".") + + System.getProperty("file.separator") + + "duke.gif"; + Icon icon = new ImageIcon(a); + IconUIResource iconResource = new IconUIResource(icon); + UIDefaults defaults = UIManager.getDefaults(); + defaults.put("Slider.horizontalThumbIcon", iconResource); + JSlider s = new JSlider(); + frame.getContentPane().add(s); + frame.setSize(250, 150); + return frame; + } +} diff --git a/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif b/test/jdk/javax/swing/plaf/metal/MetalSliderUI/4186347/duke.gif new file mode 100644 index 0000000000000000000000000000000000000000..a02a42fd606741170756cd1a33b48f609692b7f3 GIT binary patch literal 1617 zcmdUu>r)d~7>7?Fz!CwMYgeQ;%S983OoA0jYb}I;F*qYe>gWm@T%>g3RCKjoq7KRm zM%Eift#q|OSSYr!$gu6$c56UMLG9L#8nqu%I@$)QHZs#T)mG92^`GeZupi#DGw<(t zesdNrF3Qzb+|{iet#ekaB`fLq7VR30B``502l!<0YCsi0$>4v z0w56Zi=rFH;ZBrua!%eUxCJ|FXE~O#QWnZWT1XRNB1l4K)M<5EjaGvzaSX>$3`I}` zAOOWN+Ro@qM#4hASR4$xVVKD%ydZFs`Ceq@IGSN#dVeqoF|0HVd3d)QvT-~Q@gOIp zrR{cz2gxBnv|xgBf`CS}Mk7=M1wl;!LF^n%E3%vu!l#;`FHMPG z?#i1zZ+BI~>B`jRW@-KNkGfoGODjrd=HwGMrw&b5g{qHXomJO?tmeuF^H}k>3*)YB zFTWO-F`!s8pf4MG&uKrn=#F>C%FjDe^|e`^^5JejSeX8Ic$Hz>W63GWvxRFE9iOTt z^Uam%@+*I&0R4Ker|vmV3|zYkp1Z0*}z_~j|*(Jg4sVWnaCWb?($o}?o8 zA>|K)?>J&gdgZT(vVT(sXO1(Auo~WBZa7 zXU$FP4jPC5bmYI8pnfYtzRP@neXF|1cDOjX@8-0nNw3z&fsz_SGKqym&N{NI$(B-_ zb+59fLY96#Rw@2uNN?QIW}BIOWm;!=u4;vEV-j+1qz$O>QX=)WtLEmMCl%fO?g`?6Yl_mH8eUMfY% z{RPHHdHJl#+*dKx^x5-|H3iGI$W95w%?xmnj@s(^?w0mt51Fa literal 0 HcmV?d00001 diff --git a/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java b/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java new file mode 100644 index 00000000000..023f17f4c43 --- /dev/null +++ b/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/bug4969419.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4969419 + * @summary Tests that generated disabled icons have same look with Ocean + * and are updated when theme is switched + * @modules java.desktop/sun.awt + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @key headful + * @run main/manual bug4969419 + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.FlowLayout; + +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JToggleButton; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.metal.DefaultMetalTheme; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.MetalTheme; + +import sun.awt.AppContext; + +public class bug4969419 { + static final String INSTRUCTIONS = """ + When the test starts you'll see several components with icons. + Use the bottom combo box and the "Set" button to switch between + the Ocean theme and DefaultMetalTheme. + + 1. Set the Ocean theme. Ensure all the icons are the same + Note that they all are of the same brightness: none of them + can be brighter or darker than the others. + + 2. Switch to DefaultMetalTheme. Ensure all the icons changed + (became slightly darker). + + 3. Switch back to Ocean. Ensure all the icons changed + (became brighter). + """; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("bug4969419 Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(bug4969419::createUI) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("Metal Themes Icon Test"); + Container pane = frame.getContentPane(); + + LFSwitch lfswitch = new LFSwitch(pane); + if (!lfswitch.obtainOceanTheme()) { + throw new RuntimeException("No Ocean theme available"); + } + + pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS)); + + String prefix = System.getProperty("test.src", + System.getProperty("user.dir")) + System.getProperty("file.separator"); + ImageIcon icon = new ImageIcon(prefix + "duke.gif"); + + JPanel panel = new JPanel(); + JButton b = new JButton(icon); + b.setEnabled(false); + + JLabel label = new JLabel(icon, SwingConstants.LEFT); + label.setEnabled(false); + + JTabbedPane tp = new JTabbedPane(); + tp.addTab("", icon, new JPanel()); + tp.addTab("", icon, new JPanel()); + tp.setEnabledAt(0, false); + tp.setEnabledAt(1, false); + + JButton sb = new JButton(icon); + sb.setSelectedIcon(icon); + sb.setSelected(true); + sb.setEnabled(false); + + JToggleButton tb = new JToggleButton(icon); + tb.setEnabled(false); + + JToggleButton stb = new JToggleButton(icon); + stb.setSelectedIcon(icon); + stb.setSelected(true); + stb.setEnabled(false); + + pane.setBackground(Color.white); + panel.setBackground(Color.white); + b.setBackground(Color.white); + label.setBackground(Color.white); + tp.setBackground(Color.white); + sb.setBackground(Color.white); + tb.setBackground(Color.white); + stb.setBackground(Color.white); + + panel.add(b); + panel.add(label); + panel.add(tp); + panel.add(sb); + panel.add(tb); + panel.add(stb); + + pane.add(panel); + pane.add(lfswitch); + frame.setSize(400, 400); + return frame; + } + + static class LFSwitch extends JPanel { + private Component target; + static MetalTheme oceanTheme; + JComboBox lfcombo; + + public LFSwitch(Component target) { + this.target = target; + setLayout(new FlowLayout()); + lfcombo = new JComboBox(lookAndFeels); + add(lfcombo); + JButton setLfBut = new JButton("Set"); + add(setLfBut); + setLfBut.addActionListener(e -> setLf(lfcombo.getSelectedIndex(), + LFSwitch.this.target)); + } + + boolean obtainOceanTheme() { + if (oceanTheme != null) { + return true; + } + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + SwingUtilities.updateComponentTreeUI(this); + } catch (Exception e) { + JOptionPane.showMessageDialog(this, + "Unexpected error: couldn't set Metal", "Error", + JOptionPane.ERROR_MESSAGE); + return false; + } + MetalTheme theme = (MetalTheme) AppContext.getAppContext(). + get("currentMetalTheme"); + if (theme == null || theme.getName() != "Ocean") { + JOptionPane.showMessageDialog(this, + "The Ocean theme is not the default Metal theme,\n" + + "but this test requires it to be default.\n" + + "Therefore simply click PASS"); + return false; + } + oceanTheme = theme; + return true; + } + + void setLf(int idx, final Component root) { + try { + UIManager.setLookAndFeel((LookAndFeel) lfs[idx]); + if (root != null) { + SwingUtilities.updateComponentTreeUI(root); + } + } catch (UnsupportedLookAndFeelException e) { + JOptionPane.showMessageDialog(root, + "The selected look and feel is unsupported on this platform", + "Error", JOptionPane.ERROR_MESSAGE); + } catch (Exception exc) { + JOptionPane.showMessageDialog(root, + "Error setting the selected look and feel", "Error", + JOptionPane.ERROR_MESSAGE); + } + } + + static Object[] lookAndFeels = { + "Metal (Ocean)", "Metal (DefaultMetalTheme)", + }; + static Object[] lfs = { + new MetalLookAndFeel() { + protected void createDefaultTheme() { + setCurrentTheme(oceanTheme); + } + }, + new MetalLookAndFeel() { + protected void createDefaultTheme() { + MetalTheme dt = new DefaultMetalTheme(); + setCurrentTheme(dt); + } + }, + }; + } +} diff --git a/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif b/test/jdk/javax/swing/plaf/metal/OceanTheme/4969419/duke.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed32e0ff79b05c07b82863ce6fb07fa9898adaa2 GIT binary patch literal 1929 zcmWlYe^AtB8pi`HvM4_?{J2I$8$dLc1#@!R2zwgXMWdj^k;9xr+bDW&4{JlE8WpDj z7F-cwwK{H<)?L&#SJz$!;hJ{%BY2FYf)Wp^xl?aq!5Xcdi$c#hV~>m9_n-Hl=Xsy+ z=li^?*Q~;pZ+R1N1J40KRkeWM7ew3~jLM24A{CM-A}~TzqzYpq&od0GC=z71!w_=b z-==B0rt2t*nA}((5YSLs6a*Z@X__WqiSjTW6oLo{5km&|K1mGAimYjhs#wwZtvV8SV~7LCFpgub+-TTAk%UQb0dE_cj+pc?!+0o?qG$?% zVFD)%!w7Z;g)ndE8Uk6Aky=+kLaUQ{UW`XS?Nn*s@SQ{VmFgGdkV{&&98EcEQ5hjc@H$`e)fX zj@&GdchxpMUo|-A^M4iBP3(#Ib53Ap?5{nGT7SBA_V!o!TTzL5R~FUWe)4X?@iTd8 z1;TcF^rQLj?4p0uy?@ikb2eUSXdHVa_jIn=@W%a<6~57D>am6&Z!{lzc=@ZbuGB8` zpU38H8d~@82Da!+qdYG5ls&Cx?~|oPMnbqTHMw%I*KlV~?fc{rSwe29?Om}fsknG# z@n5IwY=4Mx>>0WJLG>=yJX^WbHA30iQ$H!X)3<4K zBe1|sf3NKKTS;)mg{$k(2eDJG^u5=&x{@M!V>EWgzRA((>}?o{WQBehp1mIHU!BGG zYz5_6B(+KIVdCVoum2ItM&gXZd+SB^vQTN=a zeYbbah=i-xCho2{4Pazv_i%2mH`EkM{r8XYDLbdY@(a7Ud}$%!$QrTN_DqwNXA9~g zTGKxKyfto7NDp;5A3O5zgb(hyxjN@OAG!(zy^*Ug4!yjF=Y*8aHA@ovB1({&a4;sR zTf1CVC{>Pgy`m$lG;P1$pC_6F7u%iP+qz0q4{lXT`i9g-ThiYgO^GXC`f?JNo*|@p zr{b%U-tSKw99q0|YJa9{Va?`H{IaNICo>p5lGEY*+IDR4bfIUwq~CTRuC_mGWA%~W zea{@eKJ(Iq^7MvdsPsR%&vt$@4i&s?bPptz#y#!FcRZEaMS0WFTyXMCUEfsNxnJ_9 zPwpt`Er4O>``2G{7=4r1GCSTO8#0xw+{<^L4X(K8y1wKj72KLrYD}Y7SJuY7y==wf z;UkI5?(v?h+4r;vR{P*U`ul~=D@U7K5$eV8c!%rX-38vE>azU80UrhFXCv#d`(ylZS4+i2a^vI91MTIxCx%9gd2&N&D9RC&xcpx8#f=GZv%9;F z#?CEVT%UV$nk;L%RJA+d=f8ZB@U*Xz-TZbG?HKKT(VJZMBH!)$#qRuwbFc%Aljqha zoNBs8od~V$_^vux0ZSk!iP!hI($t35SxY8`FV{pxCjpU}Ova2VIg1&>V)CvvMb_