• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / automatalib / 13138848026

04 Feb 2025 02:53PM UTC coverage: 92.108% (+2.2%) from 89.877%
13138848026

push

github

mtf90
[maven-release-plugin] prepare release automatalib-0.12.0

16609 of 18032 relevant lines covered (92.11%)

1.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.57
/visualization/dot-visualizer/src/main/java/net/automatalib/visualization/dot/DOTImageComponent.java
1
/* Copyright (C) 2013-2025 TU Dortmund University
2
 * This file is part of AutomataLib <https://automatalib.net>.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.automatalib.visualization.dot;
17

18
import java.awt.Color;
19
import java.awt.Cursor;
20
import java.awt.Dimension;
21
import java.awt.Graphics;
22
import java.awt.Point;
23
import java.awt.event.ActionEvent;
24
import java.awt.event.MouseEvent;
25
import java.awt.image.BufferedImage;
26
import java.io.IOException;
27
import java.io.Writer;
28

29
import javax.imageio.ImageIO;
30
import javax.swing.AbstractAction;
31
import javax.swing.Action;
32
import javax.swing.JComponent;
33
import javax.swing.JFileChooser;
34
import javax.swing.JOptionPane;
35
import javax.swing.JViewport;
36
import javax.swing.event.MouseInputAdapter;
37

38
import net.automatalib.common.util.IOUtil;
39
import org.checkerframework.checker.nullness.qual.Nullable;
40
import org.slf4j.Logger;
41
import org.slf4j.LoggerFactory;
42

43
/**
44
 * Component that displays a {@link BufferedImage}.
45
 */
46
final class DOTImageComponent extends JComponent {
47

48
    private static final Logger LOGGER = LoggerFactory.getLogger(DOTImageComponent.class);
2✔
49

50
    private @Nullable String dot;
51
    private @Nullable BufferedImage img;
52

53
    private final Action saveDotAction = new AbstractAction("Save DOT") {
2✔
54

55
        @Override
56
        public void actionPerformed(ActionEvent e) {
57
            final JFileChooser saveDlg = new JFileChooser();
2✔
58
            saveDlg.setFileFilter(DOTUtil.DOT_FILTER);
2✔
59
            final int result = saveDlg.showSaveDialog(DOTImageComponent.this);
2✔
60
            if (result != JFileChooser.APPROVE_OPTION) {
2✔
61
                return;
2✔
62
            }
63
            final String dot = DOTImageComponent.this.dot;
2✔
64
            if (dot == null) {
2✔
65
                throw new IllegalStateException("No DOT text has been set");
×
66
            }
67
            try (Writer w = IOUtil.asBufferedUTF8Writer(saveDlg.getSelectedFile())) {
2✔
68
                w.write(dot);
2✔
69
            } catch (IOException ex) {
×
70
                LOGGER.error("Cannot save DOT", ex);
×
71
                JOptionPane.showMessageDialog(DOTImageComponent.this,
×
72
                                              "Could not save DOT file: " + ex.getMessage(),
×
73
                                              "Cannot save DOT",
74
                                              JOptionPane.ERROR_MESSAGE);
75
            }
2✔
76
        }
2✔
77
    };
78

79
    private final Action savePngAction = new AbstractAction("Save PNG") {
2✔
80

81
        @Override
82
        public void actionPerformed(ActionEvent e) {
83
            JFileChooser chooser = new JFileChooser();
2✔
84
            chooser.setFileFilter(DOTUtil.PNG_FILTER);
2✔
85
            int result = chooser.showSaveDialog(DOTImageComponent.this);
2✔
86
            if (result != JFileChooser.APPROVE_OPTION) {
2✔
87
                return;
2✔
88
            }
89
            final BufferedImage img = DOTImageComponent.this.img;
2✔
90
            if (img == null) {
2✔
91
                throw new IllegalStateException("No image has been set");
×
92
            }
93
            try {
94
                ImageIO.write(img, "png", chooser.getSelectedFile());
2✔
95
            } catch (IOException ex) {
×
96
                LOGGER.error("Cannot save PNG", ex);
×
97
                JOptionPane.showMessageDialog(DOTImageComponent.this,
×
98
                                              "Could not save PNG file: " + ex.getMessage(),
×
99
                                              "Could not save PNG",
100
                                              JOptionPane.ERROR_MESSAGE);
101
            }
2✔
102
        }
2✔
103
    };
104

105
    /**
106
     * Default constructor.
107
     */
108
    DOTImageComponent() {
2✔
109
        final DnDMover dnDMover = new DnDMover();
2✔
110

111
        setPreferredSize(new Dimension(DOTUtil.DEFAULT_WIDTH, DOTUtil.DEFAULT_HEIGHT));
2✔
112
        addMouseListener(dnDMover);
2✔
113
        addMouseMotionListener(dnDMover);
2✔
114
    }
2✔
115

116
    /**
117
     * Sets the image to be displayed.
118
     *
119
     * @param img
120
     *         the image to be displayed
121
     */
122
    void setImage(@Nullable BufferedImage img) {
123
        this.img = img;
2✔
124
        Dimension dim;
125
        if (img != null) {
2✔
126
            dim = new Dimension(img.getWidth(), img.getHeight());
2✔
127
        } else {
128
            dim = new Dimension(DOTUtil.DEFAULT_WIDTH, DOTUtil.DEFAULT_HEIGHT);
2✔
129
        }
130

131
        setSize(dim);
2✔
132
        setPreferredSize(dim);
2✔
133
        repaint();
2✔
134
    }
2✔
135

136
    void setDotText(@Nullable String dot) {
137
        this.dot = dot;
2✔
138
    }
2✔
139

140
    void setData(@Nullable PlottedGraph pg) {
141
        if (pg == null) {
2✔
142
            this.setDotText(null);
2✔
143
            this.setImage(null);
2✔
144
        } else {
145
            this.setDotText(pg.getDotText());
2✔
146
            this.setImage(pg.getImage());
2✔
147
        }
148
    }
2✔
149

150
    /**
151
     * Retrieves an {@link Action} to save the image in a PNG file.
152
     *
153
     * @return the action
154
     */
155
    Action getSavePngAction() {
156
        return savePngAction;
2✔
157
    }
158

159
    Action getSaveDotAction() {
160
        return saveDotAction;
2✔
161
    }
162

163
    @Override
164
    protected void paintComponent(Graphics g) {
165
        g.setColor(Color.WHITE);
2✔
166
        g.fillRect(0, 0, getWidth(), getHeight());
2✔
167
        if (img != null) {
2✔
168
            g.drawImage(img, 0, 0, null);
2✔
169
        }
170
    }
2✔
171

172
    /*
173
     * Based on https://stackoverflow.com/questions/31171502/scroll-jscrollpane-by-dragging-mouse-java-swing/58815302#58815302
174
     */
175
    private class DnDMover extends MouseInputAdapter {
2✔
176

177
        private final DOTImageComponent cmp;
178
        private Point holdPointOnView;
179

180
        DnDMover() {
2✔
181
            this.cmp = DOTImageComponent.this;
2✔
182
        }
2✔
183

184
        @Override
185
        public void mousePressed(MouseEvent e) {
186
            cmp.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
2✔
187
            holdPointOnView = e.getPoint();
2✔
188
        }
2✔
189

190
        @Override
191
        public void mouseReleased(MouseEvent e) {
192
            cmp.setCursor(null);
2✔
193
        }
2✔
194

195
        @Override
196
        public void mouseDragged(MouseEvent e) {
197
            final Point dragEventPoint = e.getPoint();
2✔
198
            final JViewport viewport = (JViewport) cmp.getParent();
2✔
199

200
            assert viewport != null;
2✔
201

202
            final Point viewPos = viewport.getViewPosition();
2✔
203

204
            final int maxViewPosX = cmp.getWidth() - viewport.getWidth();
2✔
205
            final int maxViewPosY = cmp.getHeight() - viewport.getHeight();
2✔
206

207
            assert holdPointOnView != null;
2✔
208

209
            if (cmp.getWidth() > viewport.getWidth()) {
2✔
210
                viewPos.x -= dragEventPoint.x - holdPointOnView.x;
2✔
211

212
                if (viewPos.x < 0) {
2✔
213
                    viewPos.x = 0;
2✔
214
                    holdPointOnView.x = dragEventPoint.x;
2✔
215
                }
216

217
                if (viewPos.x > maxViewPosX) {
2✔
218
                    viewPos.x = maxViewPosX;
×
219
                    holdPointOnView.x = dragEventPoint.x;
×
220
                }
221
            }
222

223
            if (cmp.getHeight() > viewport.getHeight()) {
2✔
224
                viewPos.y -= dragEventPoint.y - holdPointOnView.y;
2✔
225

226
                if (viewPos.y < 0) {
2✔
227
                    viewPos.y = 0;
2✔
228
                    holdPointOnView.y = dragEventPoint.y;
2✔
229
                }
230

231
                if (viewPos.y > maxViewPosY) {
2✔
232
                    viewPos.y = maxViewPosY;
×
233
                    holdPointOnView.y = dragEventPoint.y;
×
234
                }
235
            }
236

237
            viewport.setViewPosition(viewPos);
2✔
238
        }
2✔
239
    }
240
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc