Home » Modeling » EMF » TableViewer binding
| | | | | | | | | | | |
Re: TableViewer binding [message #666357 is a reply to message #666309] |
Wed, 20 April 2011 06:42 |
Alex Mising name Messages: 61 Registered: February 2011 |
Member |
|
|
Ed, i created class WtpDbGroupItemProviderFactory:
public class WtpDbGroupItemProviderFactory extends WtpdbAdapterFactory implements ComposeableAdapterFactory, IChangeNotifier, IDisposable {
/**
* This keeps track of the root adapter factory that delegates to this adapter factory.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected ComposedAdapterFactory parentAdapterFactory;
/**
* This is used to implement {@link org.eclipse.emf.edit.provider.IChangeNotifier}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IChangeNotifier changeNotifier = new ChangeNotifier();
/**
* This keeps track of all the supported types checked by {@link #isFactoryForType isFactoryForType}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected Collection<Object> supportedTypes = new ArrayList<Object>();
/**
* This constructs an instance.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public WtpDbGroupItemProviderFactory() {
supportedTypes.add(IEditingDomainItemProvider.class);
supportedTypes.add(IStructuredItemContentProvider.class);
supportedTypes.add(ITreeItemContentProvider.class);
supportedTypes.add(IItemLabelProvider.class);
supportedTypes.add(IItemPropertySource.class);
}
/**
* This keeps track of the one adapter used for all {@link wtpdb.P6Group} instances.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected P6GroupItemProvider p6GroupItemProvider;
/**
* This creates an adapter for a {@link wtpdb.P6Group}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Adapter createP6GroupAdapter() {
if (p6GroupItemProvider == null) {
p6GroupItemProvider = new P6GroupItemProvider(this);
}
return p6GroupItemProvider;
}
/**
* This keeps track of the one adapter used for all {@link wtpdb.P6Item} instances.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected P6ItemItemProvider p6ItemItemProvider;
/**
* This creates an adapter for a {@link wtpdb.P6Item}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Adapter createP6ItemAdapter() {
if (p6ItemItemProvider == null) {
p6ItemItemProvider = new P6ItemItemProvider(this);
}
return p6ItemItemProvider;
}
/**
* This keeps track of the one adapter used for all {@link wtpdb.WtpBase} instances.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
/**
* This keeps track of the one adapter used for all {@link wtpdb.WtpBase} instances.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected WtpBaseGroupItemProvider wtpBaseGroupItemProvider;
/**
* This creates an adapter for a {@link wtpdb.WtpBase}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Adapter createWtpBaseAdapter() {
if (wtpBaseGroupItemProvider == null) {
wtpBaseGroupItemProvider = new WtpBaseGroupItemProvider(this);
}
return wtpBaseGroupItemProvider;
}
/**
* This returns the root adapter factory that contains this factory.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public ComposeableAdapterFactory getRootAdapterFactory() {
return parentAdapterFactory == null ? this : parentAdapterFactory.getRootAdapterFactory();
}
/**
* This sets the composed adapter factory that contains this factory.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setParentAdapterFactory(ComposedAdapterFactory parentAdapterFactory) {
this.parentAdapterFactory = parentAdapterFactory;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean isFactoryForType(Object type) {
return supportedTypes.contains(type) || super.isFactoryForType(type);
}
/**
* This implementation substitutes the factory itself as the key for the adapter.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Adapter adapt(Notifier notifier, Object type) {
return super.adapt(notifier, this);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object adapt(Object object, Object type) {
if (isFactoryForType(type)) {
Object adapter = super.adapt(object, type);
if (!(type instanceof Class<?>) || (((Class<?>)type).isInstance(adapter))) {
return adapter;
}
}
return null;
}
/**
* This adds a listener.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void addListener(INotifyChangedListener notifyChangedListener) {
changeNotifier.addListener(notifyChangedListener);
}
/**
* This removes a listener.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void removeListener(INotifyChangedListener notifyChangedListener) {
changeNotifier.removeListener(notifyChangedListener);
}
/**
* This delegates to {@link #changeNotifier} and to {@link #parentAdapterFactory}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void fireNotifyChanged(Notification notification) {
changeNotifier.fireNotifyChanged(notification);
if (parentAdapterFactory != null) {
parentAdapterFactory.fireNotifyChanged(notification);
}
}
/**
* This disposes all of the item providers created by this factory.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void dispose() {
if (p6GroupItemProvider != null) p6GroupItemProvider.dispose();
if (p6ItemItemProvider != null) p6ItemItemProvider.dispose();
if (wtpBaseGroupItemProvider != null) wtpBaseGroupItemProvider.dispose();
}
}
then WtpBaseGroupItemProvider:
public class WtpBaseGroupItemProvider
extends ItemProviderAdapter
implements
IEditingDomainItemProvider,
IStructuredItemContentProvider,
ITreeItemContentProvider,
IItemLabelProvider,
IItemPropertySource {
/**
* This constructs an instance from a factory and a notifier.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public WtpBaseGroupItemProvider(AdapterFactory adapterFactory) {
super(adapterFactory);
}
/**
* This returns the property descriptors for the adapted class.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public List<IItemPropertyDescriptor> getPropertyDescriptors(Object object) {
if (itemPropertyDescriptors == null) {
super.getPropertyDescriptors(object);
}
return itemPropertyDescriptors;
}
/**
* This specifies how to implement {@link #getChildren} and is used to deduce an appropriate feature for an
* {@link org.eclipse.emf.edit.command.AddCommand}, {@link org.eclipse.emf.edit.command.RemoveCommand} or
* {@link org.eclipse.emf.edit.command.MoveCommand} in {@link #createCommand}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Collection<? extends EStructuralFeature> getChildrenFeatures(Object object) {
if (childrenFeatures == null) {
super.getChildrenFeatures(object);
childrenFeatures.add(WtpdbPackage.Literals.WTP_BASE__GROUPS);
}
return childrenFeatures;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EStructuralFeature getChildFeature(Object object, Object child) {
// Check the type of the specified child object and return the proper feature to use for
// adding (see {@link AddCommand}) it as a child.
return super.getChildFeature(object, child);
}
/**
* This returns WtpBase.gif.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object getImage(Object object) {
return overlayImage(object, getResourceLocator().getImage("full/obj16/WtpBase"));
}
/**
* This returns the label text for the adapted class.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String getText(Object object) {
return getString("_UI_WtpBase_type");
}
/**
* This handles model notifications by calling {@link #updateChildren} to update any cached
* children and by creating a viewer notification, which it passes to {@link #fireNotifyChanged}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void notifyChanged(Notification notification) {
updateChildren(notification);
switch (notification.getFeatureID(WtpBase.class)) {
case WtpdbPackage.WTP_BASE__GROUPS:
fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), true, false));
return;
}
super.notifyChanged(notification);
}
/**
* This adds {@link org.eclipse.emf.edit.command.CommandParameter}s describing the children
* that can be created under this object.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected void collectNewChildDescriptors(Collection<Object> newChildDescriptors, Object object) {
super.collectNewChildDescriptors(newChildDescriptors, object);
newChildDescriptors.add
(createChildParameter
(WtpdbPackage.Literals.WTP_BASE__GROUPS,
WtpdbFactory.eINSTANCE.createP6Group()));
}
/**
* Return the resource locator for this item provider's resources.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public ResourceLocator getResourceLocator() {
return WtpEditPlugin.INSTANCE;
}
}
and in editor:
WtpDbGroupItemProviderFactory providerFactory = new WtpDbGroupItemProviderFactory();
viewer.setContentProvider(new AdapterFactoryContentProvider(providerFactory));
viewer.setInput(resource.getWtpBase());
Is this normal approach?
|
|
|
Re: TableViewer binding [message #666441 is a reply to message #666357] |
Wed, 20 April 2011 13:22 |
Ed Merks Messages: 33142 Registered: July 2009 |
Senior Member |
|
|
Alex,
I would have expected to you extend the generated item provider adapter
factory rather than duplicating it. Same goes for the one generated
item provider.
Alex wrote:
> Ed, i created class WtpDbGroupItemProviderFactory:
>
> public class WtpDbGroupItemProviderFactory extends WtpdbAdapterFactory
> implements ComposeableAdapterFactory, IChangeNotifier, IDisposable {
> /**
> * This keeps track of the root adapter factory that delegates to
> this adapter factory.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> protected ComposedAdapterFactory parentAdapterFactory;
>
> /**
> * This is used to implement {@link
> org.eclipse.emf.edit.provider.IChangeNotifier}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> protected IChangeNotifier changeNotifier = new ChangeNotifier();
>
> /**
> * This keeps track of all the supported types checked by {@link
> #isFactoryForType isFactoryForType}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> protected Collection<Object> supportedTypes = new
> ArrayList<Object>();
>
> /**
> * This constructs an instance.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public WtpDbGroupItemProviderFactory() {
> supportedTypes.add(IEditingDomainItemProvider.class);
> supportedTypes.add(IStructuredItemContentProvider.class);
> supportedTypes.add(ITreeItemContentProvider.class);
> supportedTypes.add(IItemLabelProvider.class);
> supportedTypes.add(IItemPropertySource.class);
> }
>
> /**
> * This keeps track of the one adapter used for all {@link
> wtpdb.P6Group} instances.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> protected P6GroupItemProvider p6GroupItemProvider;
>
> /**
> * This creates an adapter for a {@link wtpdb.P6Group}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Adapter createP6GroupAdapter() {
> if (p6GroupItemProvider == null) {
> p6GroupItemProvider = new P6GroupItemProvider(this);
> }
>
> return p6GroupItemProvider;
> }
>
>
> /**
> * This keeps track of the one adapter used for all {@link
> wtpdb.P6Item} instances.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> protected P6ItemItemProvider p6ItemItemProvider;
>
> /**
> * This creates an adapter for a {@link wtpdb.P6Item}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Adapter createP6ItemAdapter() {
> if (p6ItemItemProvider == null) {
> p6ItemItemProvider = new P6ItemItemProvider(this);
> }
>
> return p6ItemItemProvider;
> }
>
> /**
> * This keeps track of the one adapter used for all {@link
> wtpdb.WtpBase} instances.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
>
>
> /**
> * This keeps track of the one adapter used for all {@link
> wtpdb.WtpBase} instances.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> protected WtpBaseGroupItemProvider wtpBaseGroupItemProvider;
>
> /**
> * This creates an adapter for a {@link wtpdb.WtpBase}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Adapter createWtpBaseAdapter() {
> if (wtpBaseGroupItemProvider == null) {
> wtpBaseGroupItemProvider = new
> WtpBaseGroupItemProvider(this);
> }
>
> return wtpBaseGroupItemProvider;
> }
>
> /**
> * This returns the root adapter factory that contains this factory.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public ComposeableAdapterFactory getRootAdapterFactory() {
> return parentAdapterFactory == null ? this :
> parentAdapterFactory.getRootAdapterFactory();
> }
>
> /**
> * This sets the composed adapter factory that contains this factory.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public void setParentAdapterFactory(ComposedAdapterFactory
> parentAdapterFactory) {
> this.parentAdapterFactory = parentAdapterFactory;
> }
>
> /**
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public boolean isFactoryForType(Object type) {
> return supportedTypes.contains(type) ||
> super.isFactoryForType(type);
> }
>
> /**
> * This implementation substitutes the factory itself as the key
> for the adapter.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Adapter adapt(Notifier notifier, Object type) {
> return super.adapt(notifier, this);
> }
>
> /**
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Object adapt(Object object, Object type) {
> if (isFactoryForType(type)) {
> Object adapter = super.adapt(object, type);
> if (!(type instanceof Class<?>) ||
> (((Class<?>)type).isInstance(adapter))) {
> return adapter;
> }
> }
>
> return null;
> }
>
> /**
> * This adds a listener.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public void addListener(INotifyChangedListener
> notifyChangedListener) {
> changeNotifier.addListener(notifyChangedListener);
> }
>
> /**
> * This removes a listener.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public void removeListener(INotifyChangedListener
> notifyChangedListener) {
> changeNotifier.removeListener(notifyChangedListener);
> }
>
> /**
> * This delegates to {@link #changeNotifier} and to {@link
> #parentAdapterFactory}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public void fireNotifyChanged(Notification notification) {
> changeNotifier.fireNotifyChanged(notification);
>
> if (parentAdapterFactory != null) {
> parentAdapterFactory.fireNotifyChanged(notification);
> }
> }
>
> /**
> * This disposes all of the item providers created by this
> factory. * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public void dispose() {
> if (p6GroupItemProvider != null) p6GroupItemProvider.dispose();
> if (p6ItemItemProvider != null) p6ItemItemProvider.dispose();
> if (wtpBaseGroupItemProvider != null)
> wtpBaseGroupItemProvider.dispose();
> }
>
> }
>
> then WtpBaseGroupItemProvider:
>
> public class WtpBaseGroupItemProvider
> extends ItemProviderAdapter
> implements
> IEditingDomainItemProvider,
> IStructuredItemContentProvider,
> ITreeItemContentProvider,
> IItemLabelProvider,
> IItemPropertySource {
> /**
> * This constructs an instance from a factory and a notifier.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> public WtpBaseGroupItemProvider(AdapterFactory adapterFactory) {
> super(adapterFactory);
> }
>
> /**
> * This returns the property descriptors for the adapted class.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public List<IItemPropertyDescriptor> getPropertyDescriptors(Object
> object) {
> if (itemPropertyDescriptors == null) {
> super.getPropertyDescriptors(object);
>
> }
> return itemPropertyDescriptors;
> }
>
> /**
> * This specifies how to implement {@link #getChildren} and is
> used to deduce an appropriate feature for an
> * {@link org.eclipse.emf.edit.command.AddCommand}, {@link
> org.eclipse.emf.edit.command.RemoveCommand} or
> * {@link org.eclipse.emf.edit.command.MoveCommand} in {@link
> #createCommand}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Collection<? extends EStructuralFeature>
> getChildrenFeatures(Object object) {
> if (childrenFeatures == null) {
> super.getChildrenFeatures(object);
> childrenFeatures.add(WtpdbPackage.Literals.WTP_BASE__GROUPS) ;
> }
> return childrenFeatures;
> }
>
> /**
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> protected EStructuralFeature getChildFeature(Object object, Object
> child) {
> // Check the type of the specified child object and return the
> proper feature to use for
> // adding (see {@link AddCommand}) it as a child.
>
> return super.getChildFeature(object, child);
> }
>
> /**
> * This returns WtpBase.gif.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public Object getImage(Object object) {
> return overlayImage(object,
> getResourceLocator().getImage("full/obj16/WtpBase"));
> }
>
> /**
> * This returns the label text for the adapted class.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public String getText(Object object) {
> return getString("_UI_WtpBase_type");
> }
>
> /**
> * This handles model notifications by calling {@link
> #updateChildren} to update any cached
> * children and by creating a viewer notification, which it passes
> to {@link #fireNotifyChanged}.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public void notifyChanged(Notification notification) {
> updateChildren(notification);
>
> switch (notification.getFeatureID(WtpBase.class)) {
> case WtpdbPackage.WTP_BASE__GROUPS:
> fireNotifyChanged(new ViewerNotification(notification,
> notification.getNotifier(), true, false));
> return;
> }
> super.notifyChanged(notification);
> }
>
> /**
> * This adds {@link
> org.eclipse.emf.edit.command.CommandParameter}s describing the children
> * that can be created under this object.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> protected void collectNewChildDescriptors(Collection<Object>
> newChildDescriptors, Object object) {
> super.collectNewChildDescriptors(newChildDescriptors, object);
>
> newChildDescriptors.add
> (createChildParameter
> (WtpdbPackage.Literals.WTP_BASE__GROUPS,
> WtpdbFactory.eINSTANCE.createP6Group()));
> }
>
> /**
> * Return the resource locator for this item provider's resources.
> * <!-- begin-user-doc -->
> * <!-- end-user-doc -->
> * @generated
> */
> @Override
> public ResourceLocator getResourceLocator() {
> return WtpEditPlugin.INSTANCE;
> }
>
> }
>
> and in editor:
>
> WtpDbGroupItemProviderFactory providerFactory = new
> WtpDbGroupItemProviderFactory();
> viewer.setContentProvider(new
> AdapterFactoryContentProvider(providerFactory));
> viewer.setInput(resource.getWtpBase());
>
> Is this normal approach?
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
| | | | | |
Re: TableViewer binding [message #666638 is a reply to message #666541] |
Thu, 21 April 2011 12:14 |
Ed Merks Messages: 33142 Registered: July 2009 |
Senior Member |
|
|
Alex,
Comments beow.
Alex wrote:
> Ed, thank you for your help. One more question. I know, that using
> XyzItemProviderFactory is not good approach to use in editor class
Not sure what you mean.
>
> WtpDbReportItemProviderFactory reportFactory = new
> WtpDbReportItemProviderFactory();
> tableViewer.setLabelProvider(new AdapterFactoryLabelProvider(
> reportFactory));
> tableViewer.setContentProvider(new AdapterFactoryContentProvider(
> reportFactory));
>
> Instead i must use this:
It's fine to use this but if you want to specialize behavior for a
specific view, what you had is fine.
>
> Registry registry =
> EMFEditPlugin.getComposedAdapterFactoryDescriptorRegistry();
> adapterFactory = new ComposedAdapterFactory(registry);
> adapterFactory.addAdapterFactory(new
> ResourceItemProviderAdapterFactory());
> adapterFactory.addAdapterFactory(new
> ReflectiveItemProviderAdapterFactory());
> tableViewer.setLabelProvider(new AdapterFactoryLabelProvider(
> adapterFactory));
> tableViewer.setContentProvider(new AdapterFactoryContentProvider(
> adapterFactory));
>
>
> for this i created itemProviderAdapterFactories in EMF.Edit
> plugin.xml: one for TableViewer, and second for TreeTableViewer
>
> <factory
> uri="http://lv.psiers.wtp.datamodel.wtpdb"
> class="wtpdb.provider.WtpDbReportItemProviderFactory"
> supportedTypes=
> "org.eclipse.emf.edit.provider.IEditingDomainItemProvider
>
> org.eclipse.emf.edit.provider.IStructuredItemContentProvider
> org.eclipse.emf.edit.provider.IItemLabelProvider
> org.eclipse.emf.edit.provider.IItemPropertySource
> org.eclipse.emf.edit.provider.ITableItemLabelProvider"/>
> <factory
> uri="http://lv.psiers.wtp.datamodel.wtpdb"
> class="wtpdb.provider.WtpDbGroupItemProviderFactory"
> supportedTypes=
> "org.eclipse.emf.edit.provider.IEditingDomainItemProvider
>
> org.eclipse.emf.edit.provider.IStructuredItemContentProvider
> org.eclipse.emf.edit.provider.ITreeItemContentProvider
> org.eclipse.emf.edit.provider.IItemLabelProvider
> org.eclipse.emf.edit.provider.IItemPropertySource"/>
These look like conflicting registrations.
>
> Now i can't understand, how can i deal with my ItemProviderFactory and
> ItemProvider classes.
I thought you had it working.
Ed Merks
Professional Support: https://www.macromodeling.com/
|
|
|
Goto Forum:
Current Time: Fri Apr 26 12:25:14 GMT 2024
Powered by FUDForum. Page generated in 0.03156 seconds
|