Off Topic–How I Prepare Files for the CNC Plasma Cutter

by Bobbi Perreault 1. December 2011 13:24
Share on Facebook

It’s a hobby that I don’t have much time for, but I usually find myself doing a project with Hubby’s shop equipment right around Christmas time.   This year it’s a key-holder plaque.

I start with a concept.  We’re in Minnesota and fishing is the deal.  So I’m thinking a fish jumping out of the water.  It takes several passes, but I finally get something I like. (it’s #3)

fish

Hubby says you need a Walleye if you’re fishing in Minnesota.

fish2

Google images supplies the Walleye and some Water. I bring the images into Paint.NET (free download from here) And I use layers ( google search for tutorials here) to be able to arrange the pieces to my liking. I’m thinking I’d like to keep the water effect down through the key hooks too.

walleye

Now that I have an image that will work, I need to get it into vector format so that I can use the CNC plasma cutter (thank-you Darling Husband) to cut it out of sheet metal – that will be the canvas to be painted on.

I’ll trace that bitmap image from Paint.Net in another freely downloadable program: Inkscape (get it from here)  AND – you can get this for the Mac too.   (here’s a google search for tutorials on tracing in InkScape)

So, when I got this traced, I can save it from InkScape into a format that is supported by the CNC Plasma Cutter’s software for import – that is .dxf.   I DELETE the bitmap, leaving only outline and save it as .dxf. ( tutorials for this too)

There are some few things to remember with the traced image.   For example, holes for nails or any holes which will be cut out of the metal need to be cut out first, before the outline of your image.  So when the holes are cut out there is a solid backing.  This means the instructions for cutting them need to be at the beginning of the file (known as Z-Order).  The way I accomplish this is simple.   When I’m done I select the outline – cut it (Ctrl-X) to my clipboard.  Then paste it back into it’s former position (Ctrl-V).  Note: do this after the bitmap is removed ( all you’ll see is outline, no fill)  that makes it easier to tell if you’ve selected the right object in the document to bring the ZOrder into line.

Making sure it’s sized properly – I use scrap metal for the blank sheet metal placement.  And the stickers will be printed same size too.

I put my new .dxf file onto the data stick and head out to the shop.   Have the CNC machine do it’s magic.  GRIND off all the rough edges, Paint the sheet of metal.  Then what I do for my prototype is print a sticker of the bitmap and stick it on.   The clear coat for prototype is clear contact paper.

I think this will work – but it will have to be hand painted.  Good enough for proof of concept.

2011-12-02 07.20.39

Tags:

A Custom GridViewComboBoxColumn for Telerik Silverlight Controls

by Bobbi Perreault 8. November 2011 14:58
Share on Facebook

On a project I'm contributor at, the GridViewComboBoxColumn would show a ComboBox in the gridview cell when edit mode was active.  But if you switch away to another cell, there would be nothing showing.  (When the read only mode of the cell was active, cell was blank).  Additionally, the bound column was not receiving any updated information.

Time is always short on these projects so I opted for something quick.  Rather than trying to research how to fix my view model, I put in a custom GridViewComboBoxColumn control.   Maybe this approach would work for you.  Basically code change consists of 1. Add two classes and 2. change your Xaml to reference the custom column instead of Telerik's.

1. Create the custom control which will be embedded within the grid cell.  This may be overkill for your project – ours will use the flexibility. We have a read only mode here so that we can show the same contol to the user whether it’s being edited or not.



public class StackPanelWComboBox : StackPanel
  {
       public ComboBox cb = null;
       
      public static readonly DependencyProperty TextProperty = 
              DependencyProperty.Register("Text", typeof(String),typeof(StackPanelWComboBox), new PropertyMetadata(TextChanged)); 

      public String Text
      {
          get { return (String)GetValue(TextProperty); }
          set { SetValue(TextProperty, value); }
      }

      private static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
          StackPanelWComboBox sh = (StackPanelWComboBox)d;
          if (sh.cb == null || e.NewValue == null)
              return;
          sh.cb.SelectedValue = e.NewValue.ToString();
      }
      
      public object CommandParameter
      {
          set{ 
              if (cb == null)
                  return;
              cb.Tag = value;
          }
          get{   
              if (cb == null)
                  return null;
              return cb.Tag;
          }
      }

      public StackPanelWComboBox()
      {
      
      }

      public StackPanelWComboBox(object dataItem, double width, double minwidth, bool readOnly)
      {
          createContents(dataItem, width, minwidth, readonly);
      }

      public List<EMC_Class> ABCD
      {
          get
          {
              List<EMC_Class> lst = new List<EMC_Class>();
              foreach (var x in new EMC_Class[] 
              {
                  new EMC_Class { ClassID = 0, ClassName = "NA" },
                  new EMC_Class { ClassID = 0, ClassName = "A" },
                  new EMC_Class { ClassID = 1, ClassName = "B" },
                  new EMC_Class { ClassID = 2, ClassName = "C" },
                  new EMC_Class { ClassID = 3, ClassName = "D" }
              })
              {
                  lst.Add(x);
              }

              return lst;
          }
      }

      public class EMC_Class
      {
          public int ClassID { get; set; }
          public string ClassName { get; set; }
      }
 
      public void createContents(object dataItem, double width, double minwidth, bool readOnly)
      {
         Children.Clear();
            Orientation = Orientation.Horizontal;
            HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            Grid cbHolder = new Grid();
            tb = new ComboBox();
            tb.Width = width;
            tb.MinWidth = width;
                
            tb.DisplayMemberPath = "ClassName";
            tb.SelectedValuePath = "ClassName"; 
                

            cbHolder.Children.Add(tb);
            if (readOnly)
            {
                Rectangle rect = new Rectangle();
                rect.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
                rect.VerticalAlignment = System.Windows.VerticalAlignment.Stretch;
                rect.Fill = Application.Current.Resources["WhiteBrush"] as LinearGradientBrush;
                rect.Opacity = 0.2;
                cbHolder.Children.Add(rect);
            }

            Children.Add(cbHolder);
      }

  }

2. Create the class which will be used in place of GridViewComboBoxColumn:  ( it does inherit it though)

public class IWGridViewComboColumn : GridViewComboBoxColumn
  {
      public String Text
      {
          get
          {
              return (String)GetValue(TextProperty);
          }
          set
          {
              SetValue(TextProperty, value);
          }
      }

      public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text",
          typeof(String),
          typeof(IWGridViewComboColumn),
          new PropertyMetadata(null));

      public IWGridViewComboColumn()
      {

      }

      public override FrameworkElement CreateCellEditElement(GridViewCell cell, object dataItem)
      {
          base.CreateCellEditElement(cell, dataItem);
          var currentcontrol = cell.Content;
          if (currentcontrol != null && currentcontrol.GetType() == typeof(ComboBox))
              Text = ((ComboBox)currentcontrol).SelectedValue.ToString();

          StackPanelWComboBox panel = null;
          
          if (this.DataMemberBinding != null)
          {
              this.BindingTarget = StackPanelWComboBox.TextProperty;
          }

          if (panel == null)
          {
              panel = new StackPanelWComboBox(dataItem, ActualWidth, MinWidth, false);
          }

          if (this.DataMemberBinding != null)
          {
              panel.SetBinding(this.BindingTarget, this.CreateValueBinding());
          }

          panel.Text = Text;

          return panel as FrameworkElement;
      }

      public override FrameworkElement CreateCellElement(GridViewCell cell, object dataItem)
      {
          base.CreateCellElement(cell, dataItem);
          var currentcontrol = cell.Content;
          StackPanelWComboBox panel = null;
          if (currentcontrol != null)
          {
              panel = cell.Content as StackPanelWComboBox;
          }            

          if (this.DataMemberBinding != null)
          {
              this.BindingTarget = StackPanelWComboBox.TextProperty;
          }

          if (panel == null)
          {
              panel = new StackPanelWComboBox(dataItem, 90, 90, true);
          }

          if (this.DataMemberBinding != null)
          {
              panel.SetBinding(this.BindingTarget, this.CreateValueBinding());
          }
           panel.Text = dataItem.value;//this will depend on the value of your datatype.

          return panel;            
      }

      private Binding CreateValueBinding()
      {
          var valueBinding = new Binding();
          valueBinding.Mode = BindingMode.TwoWay;
          valueBinding.NotifyOnValidationError = true;
          valueBinding.ValidatesOnExceptions = true;
          valueBinding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
          valueBinding.Path = new PropertyPath(this.DataMemberBinding.Path.Path);
          return valueBinding;
      }

      public override void CopyPropertiesFrom(GridViewColumn source)
      {
          base.CopyPropertiesFrom(source);
          var gridViewEasyEntryTextColumn = source as IWGridViewComboColumn;
          if (gridViewEasyEntryTextColumn != null)
          {
              this.Text = gridViewEasyEntryTextColumn.Text;
          }
      }

      public override IList<ValidationError> UpdateSourceWithEditorValue(GridViewCell gridViewCell)
      {
          List<ValidationError> errors = new List<ValidationError>();
          StackPanelWComboBox editor = gridViewCell.GetEditingElement() as StackPanelWComboBox;
          BindingExpression bindingExpression = editor.ReadLocalValue(StackPanelWComboBox.TextProperty) as BindingExpression;
          if (bindingExpression != null)
          {
              bindingExpression.UpdateSource();
              errors.AddRange(Validation.GetErrors(editor));
          }
          return errors;
      }

      public override object GetNewValueFromEditor(object editor)
      {
          StackPanelWComboBox panel = editor as StackPanelWComboBox;
          if (panel != null)
          {
              panel.Text = panel.cb.SelectedValue.ToString();
              return panel.cb.SelectedValue.ToString();
          }
          else
          {
              return null;
          }
      }
  }

4. Add the namespace declaration to your Xaml class.

<UserControl
    xmlns:local="clr-namespace:THENAMESPACEOFYOURCONTROL"

5. Trade out the Telerik column in the grid view with your new custom column:

            <telerik:RadGridView   Height="250" 
                                      ShowGroupPanel="True" 
                                      VerticalAlignment="Top"
                                      AutoGenerateColumns="False" >
                    <telerik:RadGridView.Columns>
                        <local:IWGridViewComboColumn Width="100" 
                                        Header="Class"  
                                        DisplayMemberPath="ClassName"
                                        SelectedValueMemberPath="ClassID"
                                        DataMemberBinding="{Binding Class}"
                                                     ItemsSource = "{Binding ABCD}"
                                      >

That’s it.   Hopefully it’s helpful to you.

Tags:

Silverlight Custom Cursor Re-visited

by Bobbi Perreault 13. July 2011 21:28
Share on Facebook

In Silverlight 4.0 application I needed to have a line follow the mouse for comparing between line charts.  I Googled Silverlight 4.0 custom cursor and number three on the results was my old-old blog post about a custom cursor I put into a drawing program.  That took me back a ways.  ha ha.

For this app, my needs are simple, heck, I don't even need to hide the cursor.  I just want a line to follow the cursor while the mouse is over a specific panel.  So here's how I did it.

  1. I added a Path object to the XAML of my page.  This Path needs to be on top, so it's at the bottom of the XAML just before the closing </Grid>.  Visibility is turned off so it doean't intrude until needed.
    <Path Data="M122,198 L122,583.57233" Fill="#FF01010C" x:Name="cursorline"
    Visibility="Collapsed" HorizontalAlignment="Left" Grid.Row="1"
    Stretch="Fill" Stroke="Black" UseLayoutRounding="False"
    Width="1"/>
  2. I added mouse move event handlers to the containing grid, called imaginatively LayoutRoot.
    <Grid x:Name="LayoutRoot" MouseEnter="LayoutRoot_MouseEnter" 
    MouseLeave="LayoutRoot_MouseLeave"
    MouseMove="LayoutRoot_MouseMove">
  3. In Mouse Enter event handler, I set the visibility of my path to Visible.
  4. In Mouse Leave event handler, I set the visibility of my path to Collapsed.
  5. In Mouse Move event handler, I set the margin of my path to line up with the horizontal position of my cursor.  Here's the code.
            private void LayoutRoot_MouseEnter(object sender, MouseEventArgs e)
    {
    cursorline.Visibility = System.Windows.Visibility.Visible;
    }
    private void LayoutRoot_MouseLeave(object sender, MouseEventArgs e)
    {
    cursorline.Visibility = System.Windows.Visibility.Collapsed;
    }
    private void LayoutRoot_MouseMove(object sender, MouseEventArgs e)
    {
    cursorline.Margin = new Thickness( e.GetPosition(LayoutRoot).X, 0, 0, 0);

Ok then. Have a great day.

Tags:

How To

Z Follow-up to Facebook and BlogEngine.NET - Facebook app

by Bobbi Perreault 2. January 2011 18:22
Share on Facebook

 

Happy New Year all.  I was asked if the work I did last year integrating Blogengine.Net comments with Facebook notes comments turned out to be worth the time.  I thought so, at least for one of the blogs hosted at my company.  And so This is a follow-up to those posts, a summary of the benefits I've seen.

If you're interested in knowing the process or in the code, here's a summary link:  http://faxt.com/blog/search.aspx?q=facebook  

I thought it was worth-while to integrate the blog comments with Facebook.  The conversation after a post can reveal as much or more than the actual post, of course Facebook is an island and that is why this plugin was needed.  

As far as I can tell the biggest benefit has been to my Pastor's blog.  With his Facebook notes publicizing every blog post, the congregation on Facebook is able to comment on the Facebook side and that same conversation is then available on the web side.  The Facebook poster is anonymous on the web ( their numerical Facebook id is used to identify them there) 

I think it would be more useful if I took the time to integrate Akismet or some spam filter into his blog.  Because of the amount of spam coming in, I had to shorten the time allowed for comments from the Internet.  So the conversation is only able to be carried on then from the Facebook side.

But we can still at least follow it without being logged in to Facebook.

 

Keeping Image Quality High for your eCommerce Site

by Bobbi Perreault 29. December 2010 18:11
Share on Facebook

When you send an image up to a site hosted here, it will be resized as it’s uploaded to fit it within the boundaries that were defined for it on the item detail page.  Images straight from a digital camera will be very much larger than the space allotted to them.  The resizing process from large to small will result in fuzziness.

To get the crispest display, upload an image that is the same size as it is displayed at on screen.  Size and resolution matter.  Print resolution is totally different than screen resolution.

The second tool discussed here is what I recommend you use for best control. And I think this is more necessary for the images which are sized taller than they are wide. Those seem to be the ones that are most fuzzy when uploaded and resized by the website software. If you have an image taller than it is wide, use the height of the image as your setting.

For the purposes of this discussion, our ideal image size is: 

Max height: 280 pixels

Max width:  370 pixels

For this you will want a program that can edit photographs – Picasa is free and also allows you to view the images on your computer with ease.  You can download it here:

download picasa

A good video for learning how to resize with Picasa:

http://www.youtube.com/watch?v=MPUoV5uzMqY&feature=player_embedded

There’s a problem with resizing in Picasa if your images are not originally sized to a compatible height and width ratio.  Say you are working with an image which is higher than it is wide.  You can only specify width with the Picasa resize, and you won’t know what width you want your image to be if it is more tall than wide.

So, I use Paint.Net.  you can download it for free here: 

Get Paint.NET!

This article has great detailed info on how to resize using Paint.Net

http://www.wikihow.com/Resize-an-Image-With-Paint.Net

Android and Silverlight - a few thoughts

by Bobbi Perreault 24. September 2010 16:27
Share on Facebook

It's no secret that I've not been spending all my spare time on Silverlight lately.  Android's got a hold on me now.  :-)  I love working on the Android platform.  And when I get this Swing by Swing phone app off to where Terrence there can finish the mapping piece, I'll be ready to do one for EZBurn Manufacturing that will allow them to manage their inventory in the shop.  That'll be a great exercise.  Maybe I can put that out to the Android store.

There's only one problem with the Android platform development tools.  ( OK, TWO problems, but don't get me started on Eclipse.)  There's nothing that will compare to Blend for Silverlight when it comes to getting your UI smooth and professional.  I really really miss that when working with Android xml files.  

Anyone have time to write a xaml to xml converter?  Anyone know where I can find one?

Thanks for your time, have a great day.

Bobbi

Tags:

 

RSS Feed FriendFeed