一些自用代码示例
获取插件当前路径
java
import java.io.File;
import java.net.URISyntaxException;
import java.net.URL;
public class PathUtil {
public static String pluginPath() throws URISyntaxException {
// 获取当前类的 ClassLoader
URL location = PathUtil.class.getProtectionDomain().getCodeSource().getLocation();
// 将 URL 转换为文件路径
File jarFile = new File(location.toURI());
return jarFile.getParentFile().getAbsolutePath();
}
}自用——带有进度条的 Worker
展开查看
java
import com.nomagic.magicdraw.core.Application;
import org.apache.log4j.Logger;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import java.util.List;
public abstract class BaseWorker<T> extends SwingWorker<T, String> {
protected static final Logger log = Logger.getLogger(BaseWorker.class);
/**
* 进度条窗口
*/
private final ProgressBarFrame frame;
/**
* 主过程中的错误
*/
protected Exception e;
public BaseWorker() {
// 创建进度条
this.frame = new ProgressBarFrame();
frame.setVisible(true);
}
public BaseWorker(String defaultLoading) {
this.frame = new ProgressBarFrame(defaultLoading);
frame.setVisible(true);
}
/**
* worker 的主要工作
*
* @return 工作后的返回
*/
protected abstract T mainProcess() throws Exception;
/**
* 成功回调
*
* @param t 消费 worker 的返回
*/
protected abstract void onSuccess(T t) throws Exception;
protected void onError(Exception e) {
String message = e.getMessage();
if (message == null) {
message = e.getStackTrace()[0].toString();
}
log.error("onError", e);
Application.getInstance().getGUILog().showError(message);
}
@Override
protected T doInBackground() {
try {
return mainProcess();
} catch (Exception e) {
this.e = e;
}
return null;
}
@Override
protected void process(List<String> chunks) {
for (String value : chunks) {
frame.updateProgress(value);
}
}
@Override
protected void done() {
// 显示错误信息
frame.dispose();
if (e != null) {
onError(e);
} else {
try {
onSuccess(get());
} catch (Exception ex) {
onError(ex);
}
}
}
}
class ProgressBarFrame extends JFrame {
private final JProgressBar progressBar;
public ProgressBarFrame() {
this("loading...");
}
public ProgressBarFrame(String defaultLoading) {
this.progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
this.progressBar.setIndeterminate(true);
this.progressBar.setStringPainted(true);
this.progressBar.setBorderPainted(false);
this.progressBar.setString(defaultLoading);
this.add(progressBar);
this.setResizable(false);
this.setUndecorated(true);
this.setSize(300, 35);
this.setAlwaysOnTop(true);
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
this.setLocationRelativeTo(null);
}
public void updateProgress(String value) {
progressBar.setString(value);
}
}可取消的 Worker(需要在 mainProcess 中监控isCanceled()值)
java
public abstract class CancelableWorker<T> extends SwingWorker<T, String> {
protected static final Logger log = Logger.getLogger(CancelableWorker.class);
/**
* 进度条窗口
*/
private final ProgressBarFrame frame;
public CancelableWorker() {
// 创建进度条
this.frame = new ProgressBarFrame(this::cancelAction);
frame.setVisible(true);
}
public CancelableWorker(String defaultLoading) {
this.frame = new ProgressBarFrame(defaultLoading, this::cancelAction);
frame.setVisible(true);
}
/**
* worker 的主要工作
*
* @return 工作后的返回
*/
protected abstract T mainProcess() throws Exception;
/**
* 成功回调
*
* @param t 消费 worker 的返回
*/
protected abstract void onSuccess(T t) throws Exception;
protected void onError(Throwable e) {
String message = e.getMessage();
if (message == null) {
message = e.getStackTrace()[0].toString();
}
log.error("onError", e);
Application.getInstance().getGUILog().showError(message);
}
protected void cancelAction(ActionEvent e) {
this.cancel(true);
log.info("已发起取消请求...");
}
@Override
protected T doInBackground() throws Exception {
return mainProcess();
}
@Override
protected void process(List<String> chunks) {
for (String value : chunks) {
frame.updateProgress(value);
}
}
@Override
protected void done() {
// 显示错误信息
frame.dispose();
if (isCancelled()) {
log.info("成功取消...");
return;
}
try {
onSuccess(get());
} catch (ExecutionException ex) {
onError(ex.getCause());
} catch (Exception ex) {
onError(ex);
}
}
}
class ProgressBarFrame extends JFrame {
private final JProgressBar progressBar;
public ProgressBarFrame(ActionListener cancelAction) {
this("loading...", cancelAction);
}
public ProgressBarFrame(String defaultLoading, ActionListener cancelAction) {
this.progressBar = new JProgressBar(JProgressBar.HORIZONTAL);
this.progressBar.setIndeterminate(true);
this.progressBar.setStringPainted(true);
this.progressBar.setBorderPainted(false);
this.progressBar.setString(defaultLoading);
this.setLayout(new BorderLayout());
this.add(progressBar, BorderLayout.CENTER);
JButton cancelBtn = new JButton("取消");
cancelBtn.addActionListener(cancelAction);
this.add(cancelBtn, BorderLayout.EAST);
this.setResizable(false);
this.setUndecorated(true);
this.setSize(320, 30);
this.setAlwaysOnTop(true);
this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
this.setLocationRelativeTo(null);
}
public void updateProgress(String value) {
progressBar.setString(value);
}
}创建 Notification
java
private static void showNotification(String title) {
Notification notification = new Notification("com.atoz.qidsfhvf.notification.ARL", title);
NotificationManager notificationManager = NotificationManager.getInstance();
NotificationViewConfig infoConfig = notificationManager.getInfoConfig();
infoConfig.setExpirationTime(2);
notificationManager.showNotification(notification, infoConfig);
}嵌套菜单示例-带【更多】
java
ActionsCategory category = new ActionsCategory(null, "测试");
category.setNested(true);
List<MDMenuAction> topLevels = IntStream.rangeClosed(1, 20).mapToObj(i -> {
MDMenuAction topLevel = new MDMenuAction(null, "顶层节点" + i, null, null) {
@Override
public void menuSelected(MenuEvent menuEvent) {
List<MDAction> actions = IntStream.rangeClosed(i * 100, i * 100 + 15).mapToObj(j -> new MDAction(null, "次级节点" + j, null, null) {
@Override
public void actionPerformed(@CheckForNull ActionEvent actionEvent) {
Application.getInstance().getGUILog().showMessage("您点击了 " + i + ", " + j);
}
}).collect(Collectors.toList());
breakActions(this, actions, 10, "More", true);
}
};
topLevel.setNested(true);
return topLevel;
}).collect(Collectors.toList());
ActionsCategory.breakActions(category, topLevels, 10, "...", true);
ActionsConfiguratorsManager manager = ActionsConfiguratorsManager.getInstance();
AMConfigurator configurator = new AMConfigurator() {
@Override
public void configure(ActionsManager actionsManager) {
actionsManager.addCategory(category);
}
@Override
public int getPriority() {
return MEDIUM_PRIORITY;
}
};
manager.addMainMenuConfigurator(configurator);效果如下图

官方常用工具类 API
CoreHelper
- getSupplierElement
- getClientElement
- setSupplierElement
- setClientElement
InstanceSpecificationHelper
- setSlotValue
- getValueBySlot
- setValueSpecificationValue
- getValueSpecificationValue
Interactions/InteractionHelper
- getSendElement
- getReceiveElement
- setDurationInterval
- setTimeInterval
- setEventForTimeExpression
ModelHelper
- getFirstEnd
- getSecondEnd
- pureAttributes
- setConstraintText
StateMachineHelper
- getSignalForTransition
StereotypesHelper
- getProfile
- getStereotype
TagsHelper
- setStereotypePropertyValue
- getTaggedValue
ValueSpecificationHelper
- setValueSpecificationValue
- getValueSpecificationValue
Connectors/ConnectorsCollector
- collectConnectors
UsageInDiagramUtils/UsageInHelper
- UsageInDiagramUtils.getDiagramsElementUsedIn
- UsageInHelper.getUsageInInstancesElements
- UsageInHelper.getUsageInElementsWithAdditional
DSL
- getPropertyGroups
元素操作
元素类型判断
java
public static boolean isTypeOf(Element el, String typeName) {
List<Stereotype> list = el.getAppliedStereotype();
for (Stereotype stereotype : list) {
if (typeName.equals(stereotype.getName())) {
return true;
}
List<Classifier> baseClassifiers = getBaseClassifiers(stereotype);
for (Classifier classifier : baseClassifiers) {
if (typeName.equals(classifier.getName())) {
return true;
}
}
}
java.lang.Class<?> clazz = ClassTypes.getClassType(typeName);
if (clazz == null) {
return false;
}
return clazz.isAssignableFrom(el.getClass());
}
public static List<Classifier> getBaseClassifiers(Classifier classifier) {
List<Classifier> ret = new ArrayList<>();
if (classifier != null) {
recursiveBaseClassifiers(classifier, ret);
}
return ret;
}
private static void recursiveBaseClassifiers(Classifier classifier, List<Classifier> ret) {
if (classifier == null) {
return;
}
Collection<Classifier> generals = classifier.getGeneral();
if (generals == null) {
return;
}
for (Classifier general : generals) {
ret.add(general);
recursiveBaseClassifiers(general, ret);
}
}
/**
* 是否是 Block
*
* @param objInput Tree 上面挂载的元素
* @return 是否
*/
public static boolean isBlock(Object objInput) {
if (!(objInput instanceof Class)) {
return false;
}
Class obj = (Class) objInput;
if ("Block".equals(obj.getHumanType())) {
return true;
}
return isTypeOf(obj, "Block");
}
/**
* 是否是 ValueProperty
*
* @param obj 属性元素
* @return 是否
*/
public static boolean isValueProperty(Property obj) {
if ("Value Property".equals(obj.getHumanType())) {
return true;
}
return isTypeOf(obj, "ValueProperty");
}getDefaultValue
java
public static String getDefaultValueString(Property property) {
return String.valueOf(ValueSpecifications.getValueSpecificationValue(property.getDefaultValue()));
}setDefaultValue
java
public static void setDefaultValueString(Property property, String value) {
ValueSpecificationHelper.setValueSpecificationValue(property.getDefaultValue(), value);
}setDocumentation
java
private static void setDocumentation(Element owner, String mark, ElementsFactory factory) {
Collection<Comment> comments = owner.getOwnedComment();
if (!comments.isEmpty()) {
for (Comment comment : comments) {
if (comment.getAnnotatedElement().contains(owner)) {
comment.setBody(mark);
return;
}
}
}
Comment commentInstance = factory.createCommentInstance();
commentInstance.setBody(mark);
commentInstance.setOwner(owner);
commentInstance.getAnnotatedElement().add(owner);
comments.add(commentInstance);
}在模型树中选中元素
java
private static void selectElementInTree(Element el) {
SelectInBrowserTreeUtils.selectInContainmentTree(el); // 2022
// SelectInContainmentTreeAction.selectInBrowser(el); // 2021
}FlowProperty 获取方向
java
/**
* 获取 FlowProperty 的方向
*
* @param flowProperty flowProperty
* @param isConjugated 是否共轭
* @param directionDefinition 方向的 tagDefinition
* @return 处理共轭后的方向
*/
public static String getFlowPropertyDirection(Property flowProperty, boolean isConjugated, Property directionDefinition) {
TaggedValue taggedValue = TagsHelper.getTaggedValue(flowProperty, directionDefinition);
if (taggedValue == null) {
return "--";
}
List<?> values = taggedValue.getValue();
if (values.size() != 1) {
return "--";
}
NamedElement value = (NamedElement) values.get(0);
log.info(value.getName() + " " + isConjugated);
if (isConjugated) {
switch (value.getName()) {
case "in":
return "去往";
case "out":
return "接入";
case "inout":
default:
return "去往/接入";
}
} else {
switch (value.getName()) {
case "in":
return "接入";
case "out":
return "去往";
case "inout":
default:
return "去往/接入";
}
}
}getUnitName
java
/**
* 获取 ValueProperty 的单位
*
* @param property valueProperty
* @param unitProperty 单位的 tagDefinition
* @return 单位值
*/
public static String getUnitName(Property property, Property unitProperty) {
Type type = property.getType();
if (type != null) {
TaggedValue taggedValue = TagsHelper.getTaggedValue(type, unitProperty);
if (taggedValue != null) {
List<?> value = taggedValue.getValue();
Object o = value.get(0);
if (o instanceof InstanceSpecification) {
InstanceSpecification instanceSpecification = (InstanceSpecification) o;
return instanceSpecification.getName();
}
}
}
return "";
}时序图
组合片段创建和绘制
java
/**
* 创建组合片段
*
* @param factory 元素工厂
* @param interaction 交互
* @param specification 名称
* @param fromLifeLine client 生命线
* @param toLifeLine supplier 生命线
* @return 组合片段元素
*/
private static CombinedFragment createCombinedFragment(ElementsFactory factory, Interaction interaction,
String specification, Lifeline fromLifeLine, Lifeline toLifeLine) {
CombinedFragment fragment = factory.createCombinedFragmentInstance();
Collection<Lifeline> covered = fragment.getCovered();
covered.add(fromLifeLine);
covered.add(toLifeLine);
fragment.setInteractionOperator(InteractionOperatorKindEnum.OPT);
fragment.setOwner(interaction);
fragment.setName(specification);
InteractionOperand operand = factory.createInteractionOperandInstance();
operand.setOwner(fragment);
InteractionConstraint interactionConstraint = factory.createInteractionConstraintInstance();
interactionConstraint.setOwner(operand);
LiteralString literalString = factory.createLiteralStringInstance();
literalString.setOwner(interactionConstraint);
literalString.setValue(specification + "进入条件");
interactionConstraint.setSpecification(literalString);
operand.setGuard(interactionConstraint);
return fragment;
}
/**
* 绘制组合片段
*
* @param pem 绘制工厂
* @param dpe 时序图画板
* @param messagePathElements 所含消息的图形元素集合
* @param fragment 组合片段元素
*/
private static void drawCombinedFragment(PresentationElementsManager pem, DiagramPresentationElement dpe,
LinkedList<SeqBaseMessageView> messagePathElements, CombinedFragment fragment) throws ReadOnlyElementException {
SeqBaseMessageView first = messagePathElements.getFirst();
SeqBaseMessageView last = messagePathElements.getLast();
Point clientPoint1 = last.getClientPoint();
Point supplierPoint1 = last.getSupplierPoint();
int x = Math.min(clientPoint1.x, supplierPoint1.x) - 75;
int y = first.getMinY() - 50;
int width = Math.abs(clientPoint1.x - supplierPoint1.x) + 210;
int height = last.getMaxY() - first.getMinY() + 110;
ShapeElement shapeElement = pem.createShapeElement(fragment, dpe);
shapeElement.setBounds(new Rectangle(x, y, width, height));
}时间间隔创建
java
/**
* 创建时间间隔
*
* @param factory 元素工厂
* @param interaction 交互
* @param message1 消息 1
* @param message2 消息 2
* @param text 最小值
* @return 时间间隔
*/
private static DurationConstraint createDurationConstraint(ElementsFactory factory, Interaction interaction, Message message1, Message message2, String text) {
DurationConstraint durationConstraint = factory.createDurationConstraintInstance();
durationConstraint.setOwner(interaction);
durationConstraint.getConstrainedElement().add(message1);
durationConstraint.getConstrainedElement().add(message2);
InteractionHelper.setDurationInterval(durationConstraint,
text, // 最小值
null); // 最大值
return durationConstraint;
}时间约束和约束创建
java
/**
* 创建时间约束
*
* @param message 消息
* @param owner 父级(交互)
* @param text 约束内容
* @param factory 元素工厂
* @return 创建的时间约束
*/
private TimeConstraint addTimeConstraint(Message message, Element owner, String text, ElementsFactory factory) {
TimeConstraint timeConstraint = factory.createTimeConstraintInstance();
timeConstraint.setOwner(owner);
//noinspection ConstantConditions
InteractionHelper.setTimeInterval(timeConstraint, text, null);
//noinspection ConstantConditions
InteractionHelper.setEventForTimeExpression(timeConstraint.getSpecification().getMin(), message);
timeConstraint.getConstrainedElement().add(message);
return timeConstraint;
}
/**
* 创建约束
*
* @param message 消息
* @param owner 父级(交互)
* @param text 约束内容
* @param factory 元素工厂
*/
private void addConstraint(Message message, Element owner, String text, ElementsFactory factory) {
Constraint constraint = factory.createConstraintInstance();
constraint.setOwner(owner);
ModelHelper.setConstraintText(constraint, text, false, true);
constraint.getConstrainedElement().add(message);
}模块定义图
创建并绘制 Link
java
/**
* 创建并绘制 Link
*
* @param owner 父元素
* @param dpe BDD 图表
* @param pe1 Link 的其中一端的图形元素
* @param pe2 Link 的另一端的图形元素
* @return Link 的图形元素
*/
public static LinkView createAndDrawLink(Element owner, DiagramPresentationElement dpe, PresentationElement pe1, PresentationElement pe2) {
Project prj = Project.getProject(owner);
SessionManager.getInstance().checkSessionExistence(prj);
ElementsFactory f = prj.getElementsFactory();
InstanceSpecification linkIS = f.createInstanceSpecificationInstance();
linkIS.setOwner(owner);
UmlPresentationElementCreator creator = new UmlPresentationElementCreator(dpe);
creator.getConfig().setSelectCreated(false);
DiagramWindow window = prj.getProjectDiagramWindowsManager().getWindow(dpe);
if (window != null) {
window.getPanel().repaint();
}
return (LinkView) creator.createPathElement(linkIS, pe1, pe2, prj.getCommandForAppending());
}在 Magicdraw 右侧创建 Panel 面板示例
java
public class MyTestPlugin extends Plugin {
private final static WindowComponentInfo info = new WindowComponentInfo("COMPONENT_ID", "COMPONENT_NAME", null,
ProjectWindowsManager.SIDE_EAST,
ProjectWindowsManager.STATE_DOCKED,
false);
@Override
public void init() {
Browser.addBrowserInitializer(new Browser.BrowserInitializer() {
@Override
public void init(Browser browser, Project project) {
browser.addPanel(new BrowserPanel());
}
@Override
public WindowComponentInfoRegistration getInfo() {
return new WindowComponentInfoRegistration(info, null);
}
});
}
@Override
public boolean close() {
return true;
}
@Override
public boolean isSupported() {
return true;
}
static class BrowserPanel extends ExtendedPanel implements WindowComponent {
/**
* Constructor.
*/
public BrowserPanel() {
JLabel label = new JLabel("BrowserPanel");
label.setHorizontalAlignment(SwingConstants.CENTER);
add(label, BorderLayout.CENTER);
}
@Override
public WindowComponentInfo getInfo() {
return info;
}
@Override
public WindowComponentContent getContent() {
return new WindowComponentContent() {
@Override
public Component getWindowComponent() {
return BrowserPanel.this;
}
@Override
public Component getDefaultFocusComponent() {
return BrowserPanel.this;
}
};
}
}
}创建带选中状态的菜单项
java
public class SimpleStateAction extends MDStateAction {
private boolean iAmSelected;
/**
* Constructor for SimpleStateAction.
*
* @param id action id
* @param name action name
*/
public SimpleStateAction(String id, String name)
{
super(id, name, null, null);
}
/**
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
// changing state
iAmSelected = !iAmSelected;
// showing changes
JOptionPane.showMessageDialog(MDDialogParentProvider.getProvider().getDialogOwner(), "This is:" + getName() + " checked:" + iAmSelected);
}
/**
* @see com.nomagic.actions.NMAction#updateState()
*/
@Override
public void updateState() {
setState(iAmSelected);
}
}创建单选组的菜单项
java
private static NMAction getGroupedStateAction()
{
String[] choice = new String[1];
SimpleChoiceAction a1 = new SimpleChoiceAction("R1", "R1", choice);
SimpleChoiceAction a2 = new SimpleChoiceAction("R2", "R2", choice);
choice[0] = a1.getName();
a1.updateState();
a2.updateState();
// actions must be added to one category.
ActionsCategory cat = new ActionsCategory();
cat.addAction(a1);
cat.addAction(a2);
return cat;
}
public class SimpleChoiceAction extends MDStateAction
{
/**
* Current choice value. Value is shared between several actions.
*/
private final String[] currentChoice;
/**
* Constructor for SimpleChoiceAction.
*
* @param id Action id
* @param name action name
* @param currentChoice shared choice value
*/
public SimpleChoiceAction(String id, String name, String[] currentChoice)
{
super(id, name, null, null);
setGrouped(true);
this.currentChoice = currentChoice;
}
/**
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e)
{
// changing choice only when it is not already selected.
if (!getState())
{
currentChoice[0] = getName();
// showing information about changes
JOptionPane.showMessageDialog(MDDialogParentProvider.getProvider().getDialogOwner(), "Selected:" + getName());
}
// updating other actions state, making only one action from group selected.
// This can be done in several ways, one way is to call for every action updateState() method.
// If action execution will create session, actions will be updated automatically.
ActionsStateUpdater.updateActionsState();
}
/**
* @see com.nomagic.actions.NMAction#updateState()
*/
@Override
public void updateState()
{
// setting this action state to true only when it is current choice.
setState(getName().equals(currentChoice[0]));
}
}