# SPDX-License-Identifier: LGPL-2.1-or-later

#***************************************************************************
#*   Copyright (c) 2012 Sebastian Hoogen <github@sebastianhoogen.de>       *
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   This program 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 Library General Public License for more details.                  *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with this program; if not, write to the Free Software   *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#***************************************************************************

__title__ = "FreeCAD OpenSCAD Workbench - GUI Commands"
__author__ = "Sebastian Hoogen"
__url__ = ["https://www.freecad.org"]

'''
This Script includes the GUI Commands of the OpenSCAD module
'''

import FreeCAD
import OpenSCADUtils

if FreeCAD.GuiUp:
    import FreeCADGui
    from PySide import QtCore, QtGui
    gui = True
else:
    gui = False

translate = FreeCAD.Qt.translate

class ExplodeGroup:
    "Ungroup Objects"
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0

    def Activated(self):
        def isdefault(shapecolor):
            def comparefloat(f1,f2):
                if f1 == 0.0:
                    return f1 == f2
                else:
                    return abs((f1-f2)/f1) < 2**-24
            scol=FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetUnsigned('DefaultShapeColor',0xccccccff)
            defaultcolor = (((scol >> 24) & 0xff) / 255.0,
                           ((scol >> 16) & 0xff) / 255.0,
                           ((scol >>  8) & 0xff) / 255.0, 0.0)
            return all(all(comparefloat(fcc,dcc) for fcc,dcc in \
                    zip(facecolor,defaultcolor))  for facecolor in shapecolor)

        def isgrey(shapecolor):
            defaultcolor=(float.fromhex('0x1.99999ap-1'),float.fromhex(\
                    '0x1.99999ap-1'),float.fromhex('0x1.99999ap-1'),0.0)
            return all(facecolor == defaultcolor  for facecolor in shapecolor)

        def randomcolor(transp=0.0):
            import random
            return (random.random(),random.random(),random.random(),transp)

        def explode(obj,color=True):
            if obj.isDerivedFrom('Part::Fuse') or \
                    obj.isDerivedFrom('Part::MultiFuse') or \
                    obj.isDerivedFrom('Part::Compound'):
                plm = obj.Placement
                outlist = obj.OutList[:]
                if plm.isNull() or all((len(oo.InList)==1 and \
                        not oo.isDerivedFrom('PartDesign::Feature')) \
                        for oo in obj.OutList):
                    obj.Document.removeObject(obj.Name)
                    for oo in outlist:
                        if not plm.isNull():
                            oo.Placement=plm.multiply(oo.Placement)
                        if FreeCAD.GuiUp:
                            import FreeCADGui
                            oo.ViewObject.show()
                            if color and isdefault(oo.ViewObject.DiffuseColor):
                                if color:
                                    oo.ViewObject.DiffuseColor=randomcolor()
                                else:
                                    oo.ViewObject.DiffuseColor=color
                else:
                    FreeCAD.Console.PrintError(translate('OpenSCAD', 'Unable to explode %s') % obj.Name + '\n')

        for obj in FreeCADGui.Selection.getSelection():
            if len(obj.InList) == 0: # allowed only for for top level objects
                explode(obj)

    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_Explode_Group',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExplodeGroup', 'Explode Group'),
                'ToolTip':  QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExplodeGroup', 'Explodes a fusion or compound and applies random colors')}

class ColorCodeShape:
    "Change the Color of selected or all Shapes based on their validity"
    def Activated(self):
        import colorcodeshapes
        selection=FreeCADGui.Selection.getSelectionEx()
        if len(selection) > 0:
            objs=[selobj.Object for selobj in selection]

        else:
            objs=FreeCAD.ActiveDocument.Objects
        colorcodeshapes.colorcodeshapes(objs)
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_ColorCodeShape',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ColorCodeShape', 'Color Shapes'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ColorCodeShape', 'Colors shapes by validity and type')}

class Edgestofaces:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0

    def Activated(self):
        from OpenSCAD2Dgeom import edgestofaces,Overlappingfaces
        selection=FreeCADGui.Selection.getSelectionEx()
        edges=[]
        for selobj in selection:
            edges.extend(selobj.Object.Shape.Edges)
        Overlappingfaces(edgestofaces(edges,None)).makefeatures(FreeCAD.ActiveDocument)
        for selobj in selection:
            selobj.Object.ViewObject.hide()
        FreeCAD.ActiveDocument.recompute()

    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_Edgestofaces',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Edgestofaces', 'Convert Edges to Faces'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD', 'Converts edges to faces')}

class RefineShapeFeature:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0

    def Activated(self):
        import Part
        import OpenSCADFeatures
        selection=FreeCADGui.Selection.getSelectionEx()
        for selobj in selection:
            newobj=selobj.Document.addObject("Part::FeaturePython",'refine')
            OpenSCADFeatures.RefineShape(newobj,selobj.Object)
            OpenSCADFeatures.ViewProviderTree(newobj.ViewObject)
            newobj.Label='refine_%s' % selobj.Object.Label
            selobj.Object.ViewObject.hide()
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_RefineShapeFeature',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RefineShapeFeature', 'Refine Shape Feature'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RefineShapeFeature', 'Creates a refined shape')}

class MirrorMeshFeature:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Mesh::Feature') > 0

    def Activated(self):
        selection=FreeCADGui.Selection.getSelectionEx()
        for selobj in selection:
            newobj=selobj.Document.addObject("Mesh::Feature",'mirror')
            newobj.Label='mirror_%s' % selobj.Object.Label
            msh=selobj.Object.Mesh
            items=["[1;0;0]","[0;1;0]","[0;0;1]","[1;1;0]","[0;1;1]","[1;0;1]","[1;1;1]"]
            item, ok = QtGui.QInputDialog.getItem(QtGui.QApplication.activeWindow(),'Mirror about which Axis?','Select Axis (or enter custom value):',items,editable=True)
            if ok:
                splits = list(item.replace('[','').replace(']','').split(';'))
                x = float(splits[0])
                y = float(splits[1])
                z = float(splits[2])
                vec = FreeCAD.Base.Vector(x,y,z)
                newmesh=OpenSCADUtils.mirrormesh(msh, vec)
                newobj.Mesh=newmesh
                selobj.Object.ViewObject.hide()
            else:
                selobj.Document.removeObject(newobj.Name)

        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_MirrorMeshFeature',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MirrorMeshFeature', 'Mirror Mesh Feature'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MirrorMeshFeature', 'Mirrors the mesh')}

class ScaleMeshFeature:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Mesh::Feature') > 0

    def Activated(self):
        selection=FreeCADGui.Selection.getSelectionEx()
        for selobj in selection:
            newobj=selobj.Document.addObject("Mesh::Feature",'scale')
            newobj.Label='scale_%s' % selobj.Object.Label
            msh=selobj.Object.Mesh
            items=["[1;1;1]"]
            item, ok = QtGui.QInputDialog.getItem(QtGui.QApplication.activeWindow(),'Scale about which Axis?','Enter scaling value:',items,editable=True)
            if ok:
                splits = list(item.replace('[','').replace(']','').split(';'))
                x = float(splits[0])
                y = float(splits[1])
                z = float(splits[2])
                vec = FreeCAD.Base.Vector(x,y,z)
                newmesh=OpenSCADUtils.scalemesh(msh, vec)
                newobj.Mesh=newmesh
                selobj.Object.ViewObject.hide()
            else:
                selobj.Document.removeObject(newobj.Name)
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_ScaleMeshFeature',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ScaleMeshFeature', 'Scale Mesh Feature'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ScaleMeshFeature', 'Scales the mesh')}


class ResizeMeshFeature:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Mesh::Feature') > 0

    def Activated(self):
        selection=FreeCADGui.Selection.getSelectionEx()
        for selobj in selection:
            newobj=selobj.Document.addObject("Mesh::Feature",'resize')
            newobj.Label='resize_%s' % selobj.Object.Label
            msh=selobj.Object.Mesh
            items=["[1;1;1]"]
            item, ok = QtGui.QInputDialog.getItem(QtGui.QApplication.activeWindow(),'Resize about which Axis?','Enter resizing value:',items,editable=True)
            if ok:
                splits = list(item.replace('[','').replace(']','').split(';'))
                x = float(splits[0])
                y = float(splits[1])
                z = float(splits[2])
                vec = FreeCAD.Base.Vector(x,y,z)
                newmesh=OpenSCADUtils.resizemesh(msh, vec)
                newobj.Mesh=newmesh
                selobj.Object.ViewObject.hide()
            else:
                selobj.Document.removeObject(newobj.Name)
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_ResizeMeshFeature',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ResizeMeshFeature', 'Resize Mesh Feature'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ResizeMeshFeature', 'Resizes the mesh')}


class IncreaseToleranceFeature:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0

    def Activated(self):
        import Part
        import OpenSCADFeatures
        selection=FreeCADGui.Selection.getSelectionEx()
        for selobj in selection:
            newobj=selobj.Document.addObject("Part::FeaturePython",'tolerance')
            OpenSCADFeatures.IncreaseTolerance(newobj,selobj.Object)
            OpenSCADFeatures.ViewProviderTree(newobj.ViewObject)
            newobj.Label='tolerance_%s' % selobj.Object.Label
            selobj.Object.ViewObject.hide()
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_IncreaseToleranceFeature',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_IncreaseToleranceFeature', 'Increase Tolerance Feature'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_IncreaseToleranceFeature', 'Creates a feature to increase the tolerance')}

class ExpandPlacements:
    '''This should aid interactive repair in the future
    but currently it breaks extrusions, as axis, base and so on have to be
    recalculated'''
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0

    def Activated(self):
        import expandplacements
        for selobj in FreeCADGui.Selection.getSelectionEx():
            expandplacements.expandplacements(selobj.Object,FreeCAD.Placement())
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_ExpandPlacements',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExpandPlacements', 'Expand Placements'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ExpandPlacements', 'Expands all placements downwards in the Tree View')}

class ReplaceObject:
    def IsActive(self):
        nobj = FreeCADGui.Selection.countObjectsOfType('Part::Feature')
        if nobj == 3: return True
        elif nobj == 2: return tuple((len(obj.InList)) for obj in \
                FreeCADGui.Selection.getSelection()) in ((0,1),(1,0))
        #else: return False

    def Activated(self):
        import replaceobj
        objs=FreeCADGui.Selection.getSelection()
        if len(objs)==3 or \
                tuple((len(obj.InList)) for obj in objs) in ((0,1),(1,0)):
            replaceobj.replaceobjfromselection(objs)
        else:
            FreeCAD.Console.PrintError(translate('OpenSCAD', 'Select 3 objects first')+ '\n')
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_ReplaceObject',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ReplaceObject', 'Replace Object'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_ReplaceObject', 'Replaces an object in the Tree View')}

class RemoveSubtree:
    def IsActive(self):
        return FreeCADGui.Selection.countObjectsOfType('Part::Feature') > 0
    def Activated(self):
        import OpenSCADUtils
        import FreeCADGui
        OpenSCADUtils.removesubtree(FreeCADGui.Selection.getSelection())

    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_RemoveSubtree',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RemoveSubtree', 'Remove Objects and Children'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_RemoveSubtree', 'Removes the selected objects and all children that are not referenced by other objects')}

class AddSCADWidget(QtGui.QWidget):
    def __init__(self,*args):
        QtGui.QWidget.__init__(self,*args)
        # Main text area
        self.textEdit=QtGui.QTextEdit()
        self.textEdit.setAcceptRichText(False)

        # Message Area
        self.textMsg=QtGui.QPlainTextEdit()
        self.textMsg.setReadOnly(True)
        h = int(2.5 * self.textMsg.fontMetrics().height())
        self.textMsg.setMaximumHeight(h)
        self.textMsg.resize(self.textMsg.width(),h)
        self.buttonadd = QtGui.QPushButton(translate('OpenSCAD','Add'))
        self.buttonrefresh = QtGui.QPushButton(translate('OpenSCAD','Refresh'))
        self.buttonclear = QtGui.QPushButton(translate('OpenSCAD','Clear Code'))
        self.buttonload = QtGui.QPushButton(translate('OpenSCAD','Open…'))
        self.buttonsave = QtGui.QPushButton(translate('OpenSCAD','Save…'))
        self.checkboxmesh = QtGui.QCheckBox(translate('OpenSCAD','as mesh'))
        layouth=QtGui.QHBoxLayout()
        layouth.addWidget(self.buttonadd)
        layouth.addWidget(self.buttonrefresh)
        layouth.addWidget(self.buttonload)
        layouth.addWidget(self.buttonsave)
        layouth.addWidget(self.buttonclear)
        layout= QtGui.QVBoxLayout()
        layout.addLayout(layouth)
        layout.addWidget(self.checkboxmesh)
        layout.addWidget(self.textEdit)
        layout.addWidget(self.textMsg)
        self.setLayout(layout)
        self.setWindowTitle(translate('OpenSCAD','Add OpenSCAD Element'))
        self.textEdit.setText(u'cube();')

        def undoable_clear():
            """Clears the textEdit in a way that allows undo of the action"""
            self.textEdit.setFocus()
            self.textEdit.selectAll()
            keypress = QtGui.QKeyEvent(QtGui.QKeyEvent.KeyPress, QtCore.Qt.Key_Delete, QtCore.Qt.NoModifier)
            QtGui.QGuiApplication.sendEvent(self.textEdit, keypress)

        self.buttonclear.clicked.connect(undoable_clear)

    def retranslateUi(self, widget=None):
        self.buttonadd.setText(translate('OpenSCAD','Add'))
        self.buttonload.setText(translate('OpenSCAD','Load'))
        self.buttonsave.setText(translate('OpenSCAD','Save'))
        self.buttonrefresh.setText(translate('OpenSCAD','Refresh'))
        self.buttonclear.setText(translate('OpenSCAD','Clear'))
        self.checkboxmesh.setText(translate('OpenSCAD','as Mesh'))
        self.setWindowTitle(translate('OpenSCAD','Add OpenSCAD Element'))

class AddSCADTask:
    def __init__(self):
        self.form = AddSCADWidget()
        self.form.buttonadd.clicked.connect(self.addelement)
        self.form.buttonload.clicked.connect(self.loadelement)
        self.form.buttonsave.clicked.connect(self.saveelement)
        self.form.buttonrefresh.clicked.connect(self.refreshelement)

    def getStandardButtons(self):
        return QtGui.QDialogButtonBox.Close

    def isAllowedAlterSelection(self):
        return True

    def isAllowedAlterView(self):
        return True

    def isAllowedAlterDocument(self):
        return True

    def addelement(self):
        scadstr=self.form.textEdit.toPlainText()
        asmesh=self.form.checkboxmesh.checkState()
        import OpenSCADUtils
        import os
        extension= 'stl' if asmesh else 'csg'
        try:
            tmpfilename=OpenSCADUtils.callopenscadstring(scadstr,extension)
            doc=FreeCAD.activeDocument() or FreeCAD.newDocument()
            if asmesh:
                import Mesh
                Mesh.insert(tmpfilename,doc.Name)
            else:
                import importCSG
                importCSG.insert(tmpfilename,doc.Name)
            try:
                os.unlink(tmpfilename)
            except OSError:
                pass

        except OpenSCADUtils.OpenSCADError as e:
            self.form.textMsg.setPlainText(e.value)
            FreeCAD.Console.PrintError(e.value)

    def refreshelement(self):
        self.form.textMsg.setPlainText('')
        doc=FreeCAD.activeDocument()
        if doc :
            for obj in doc.Objects :
                doc.removeObject(obj.Name)
        self.addelement()

    def loadelement(self):
        filename, _ = QtGui.QFileDialog.getOpenFileName(
            parent=self.form,
            caption=translate("OpenSCAD", "Open file"),
            dir='.',
            filter=translate("OpenSCAD", "OpenSCAD Files") + " (*.scad *.csg)"
        )

        if filename:
            print('filename :'+filename)
            with open(filename,'r') as fp :
                data = fp.read()
                self.form.textEdit.setText(data)

    def saveelement(self) :
        filename, _ = QtGui.QFileDialog.getSaveFileName(
            parent=self.form,
            caption=translate("OpenSCAD", "Save file"),
            dir='.',
            filter=translate("OpenSCAD", "OpenSCAD Files") + " (*.scad *.csg)"
        )

        if filename:
            Text = self.form.textEdit.toPlainText()
            with open(filename,'w') as fp :
                fp.write(Text)

class OpenSCADMeshBooleanWidget(QtGui.QWidget):
    def __init__(self,*args):
        QtGui.QWidget.__init__(self,*args)
        #self.textEdit=QtGui.QTextEdit()
        self.buttonadd = QtGui.QPushButton(translate('OpenSCAD','Perform'))
        self.rb_group = QtGui.QButtonGroup()
        self.rb_group_box = QtGui.QGroupBox()
        self.rb_group_box_layout = QtGui.QVBoxLayout()
        self.rb_group_box.setLayout(self.rb_group_box_layout)
        self.rb_union = QtGui.QRadioButton("Union")
        self.rb_group.addButton(self.rb_union)
        self.rb_group_box_layout.addWidget(self.rb_union)
        self.rb_intersection = QtGui.QRadioButton("Intersection")
        self.rb_group.addButton(self.rb_intersection)
        self.rb_group_box_layout.addWidget(self.rb_intersection)
        self.rb_difference = QtGui.QRadioButton("Difference")
        self.rb_group.addButton(self.rb_difference)
        self.rb_group_box_layout.addWidget(self.rb_difference)
        self.rb_hull = QtGui.QRadioButton("Hull")
        self.rb_group.addButton(self.rb_hull)
        self.rb_group_box_layout.addWidget(self.rb_hull)
        self.rb_minkowski = QtGui.QRadioButton("Minkowski sum")
        self.rb_group.addButton(self.rb_minkowski)
        self.rb_group_box_layout.addWidget(self.rb_minkowski)
        layouth=QtGui.QHBoxLayout()
        layouth.addWidget(self.buttonadd)
        layout= QtGui.QVBoxLayout()
        layout.addLayout(layouth)
        layout.addWidget(self.rb_group_box)
        self.setLayout(layout)
        self.setWindowTitle(translate('OpenSCAD','Mesh Boolean'))

    def retranslateUi(self, widget=None):
        self.buttonadd.setText(translate('OpenSCAD','Perform'))
        self.setWindowTitle(translate('OpenSCAD','Mesh Boolean'))
        self.rb_minkowski.setText(translate('OpenSCAD','Minkowski sum'))

class OpenSCADMeshBooleanTask:
    def __init__(self):
        self.form = OpenSCADMeshBooleanWidget()
        self.form.buttonadd.clicked.connect(self.doboolean)

    def getStandardButtons(self):
        return QtGui.QDialogButtonBox.Close

    def isAllowedAlterSelection(self):
        return False

    def isAllowedAlterView(self):
        return False

    def isAllowedAlterDocument(self):
        return True

    def doboolean(self):
        from OpenSCADUtils import meshoponobjs
        if self.form.rb_intersection.isChecked(): opname = 'intersection'
        elif self.form.rb_difference.isChecked(): opname = 'difference'
        elif self.form.rb_hull.isChecked():       opname = 'hull'
        elif self.form.rb_minkowski.isChecked():  opname = 'minkowski'
        else: opname = 'union'
        newmesh,objsused = meshoponobjs(opname,FreeCADGui.Selection.getSelection())
        if len(objsused) > 0:
            newmeshobj = FreeCAD.activeDocument().addObject('Mesh::Feature',opname) #create a Feature for the result
            newmeshobj.Mesh = newmesh #assign the result to the new Feature
            for obj in objsused:
                obj.ViewObject.hide() #hide the selected Features

class AddOpenSCADElement:
    def IsActive(self):
        return not FreeCADGui.Control.activeDialog()

    def Activated(self):
        panel = AddSCADTask()
        FreeCADGui.Control.showDialog(panel)

    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_AddOpenSCADElement',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_AddOpenSCADElement', 'Add OpenSCAD Element'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_AddOpenSCADElement',
                            'Adds an OpenSCAD element based on entered OpenSCAD code using the OpenSCAD binary')}

class OpenSCADMeshBoolean:
    def IsActive(self):
        return not FreeCADGui.Control.activeDialog() and \
            len(FreeCADGui.Selection.getSelection()) >= 1

    def Activated(self):
        panel = OpenSCADMeshBooleanTask()
        FreeCADGui.Control.showDialog(panel)

    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_MeshBooleans',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MeshBoolean','Mesh Boolean'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_MeshBoolean',
                            'Performs a boolean operation using the OpenSCAD binary')}

class Hull:
    def IsActive(self):
        return len(FreeCADGui.Selection.getSelection()) >= 1

    def Activated(self):
        import Part
        import OpenSCADFeatures
        import importCSG
        selection=FreeCADGui.Selection.getSelectionEx()
        objList = []
        for selobj in selection:
            objList.append(selobj.Object)
            selobj.Object.ViewObject.hide()
        importCSG.process_ObjectsViaOpenSCAD(FreeCAD.activeDocument(),objList,"hull")
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_Hull',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Hull', 'Hull'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Hull', 'Creates a hull')}

class Minkowski:
    def IsActive(self):
        return len(FreeCADGui.Selection.getSelection()) >= 1

    def Activated(self):
        import Part
        import OpenSCADFeatures
        import importCSG
        selection=FreeCADGui.Selection.getSelectionEx()
        objList = []
        for selobj in selection:
            objList.append(selobj.Object)
            selobj.Object.ViewObject.hide()
        importCSG.process_ObjectsViaOpenSCAD(FreeCAD.activeDocument(),objList,"minkowski")
        FreeCAD.ActiveDocument.recompute()
    def GetResources(self):
        return {'Pixmap'  : 'OpenSCAD_Minkowski',
                'MenuText': QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Minkowski', 'Minkowski Sum'),
                'ToolTip' : QtCore.QT_TRANSLATE_NOOP('OpenSCAD_Minkowski', 'Creates a Minkowski sum')}

FreeCADGui.addCommand('OpenSCAD_ColorCodeShape',ColorCodeShape())
FreeCADGui.addCommand('OpenSCAD_ExplodeGroup',ExplodeGroup())
FreeCADGui.addCommand('OpenSCAD_Edgestofaces',Edgestofaces())
FreeCADGui.addCommand('OpenSCAD_RefineShapeFeature',RefineShapeFeature())
FreeCADGui.addCommand('OpenSCAD_MirrorMeshFeature',MirrorMeshFeature())
FreeCADGui.addCommand('OpenSCAD_ScaleMeshFeature',ScaleMeshFeature())
FreeCADGui.addCommand('OpenSCAD_ResizeMeshFeature',ResizeMeshFeature())
FreeCADGui.addCommand('OpenSCAD_IncreaseToleranceFeature',IncreaseToleranceFeature())
FreeCADGui.addCommand('OpenSCAD_ExpandPlacements',ExpandPlacements())
FreeCADGui.addCommand('OpenSCAD_ReplaceObject',ReplaceObject())
FreeCADGui.addCommand('OpenSCAD_RemoveSubtree',RemoveSubtree())
FreeCADGui.addCommand('OpenSCAD_AddOpenSCADElement',AddOpenSCADElement())
FreeCADGui.addCommand('OpenSCAD_MeshBoolean',OpenSCADMeshBoolean())
FreeCADGui.addCommand('OpenSCAD_Hull',Hull())
FreeCADGui.addCommand('OpenSCAD_Minkowski',Minkowski())
