2009-04-19 18:07:22 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* 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 General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
2014-01-23 13:36:51 +00:00
using System ;
2009-04-19 18:07:22 +00:00
using System.ComponentModel ;
2014-10-17 11:55:08 +00:00
using System.Drawing ;
2009-04-19 18:07:22 +00:00
using System.Globalization ;
using System.Windows.Forms ;
#endregion
namespace CodeImp.DoomBuilder.Controls
{
public class NumericTextbox : AutoSelectTextbox
{
#region = = = = = = = = = = = = = = = = = = Constants
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
2014-01-23 13:36:51 +00:00
private bool allownegative ; // Allow negative numbers
private bool allowrelative ; // Allow ++, --, * and / prefix for relative changes
private bool allowdecimal ; // Allow decimal (float) numbers
private bool controlpressed ;
2015-03-23 14:19:23 +00:00
private bool shiftpressed ; //mxd
2014-10-17 11:55:08 +00:00
private readonly ToolTip tooltip ; //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public bool AllowNegative { get { return allownegative ; } set { allownegative = value ; } }
2014-10-17 11:55:08 +00:00
public bool AllowRelative { get { return allowrelative ; } set { allowrelative = value ; UpdateTextboxStyle ( ) ; } }
public bool AllowDecimal { get { return allowdecimal ; } set { allowdecimal = value ; } }
2009-04-19 18:07:22 +00:00
2015-03-23 14:19:23 +00:00
public bool ControlPressed { get { return controlpressed ; } } //mxd
public bool ShiftPressed { get { return shiftpressed ; } } //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
public NumericTextbox ( )
{
this . ImeMode = ImeMode . Off ;
2014-10-17 11:55:08 +00:00
//mxd. Setup tooltip
this . tooltip = new ToolTip { AutomaticDelay = 100 , AutoPopDelay = 4000 , InitialDelay = 100 , ReshowDelay = 100 } ;
2009-04-19 18:07:22 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Methods
// Key pressed
protected override void OnKeyDown ( KeyEventArgs e )
{
controlpressed = e . Control ;
2015-03-23 14:19:23 +00:00
shiftpressed = e . Shift ; //mxd
2009-04-19 18:07:22 +00:00
base . OnKeyDown ( e ) ;
}
// Key released
protected override void OnKeyUp ( KeyEventArgs e )
{
controlpressed = e . Control ;
2015-03-23 14:19:23 +00:00
shiftpressed = e . Shift ; //mxd
2009-04-19 18:07:22 +00:00
base . OnKeyUp ( e ) ;
}
// When a key is pressed
protected override void OnKeyPress ( KeyPressEventArgs e )
{
string allowedchars = "0123456789\b" ;
// Determine allowed chars
if ( allownegative ) allowedchars + = CultureInfo . CurrentUICulture . NumberFormat . NegativeSign ;
2014-01-23 13:36:51 +00:00
if ( allowrelative ) allowedchars + = "+-*/" ; //mxd
2009-04-19 18:07:22 +00:00
if ( controlpressed ) allowedchars + = "\u0018\u0003\u0016" ;
2014-01-23 13:36:51 +00:00
if ( allowdecimal | | this . Text . StartsWith ( "*" ) | | this . Text . StartsWith ( "/" ) ) //mxd
allowedchars + = CultureInfo . CurrentUICulture . NumberFormat . NumberDecimalSeparator ;
2009-04-19 18:07:22 +00:00
// Check if key is not allowed
if ( allowedchars . IndexOf ( e . KeyChar ) = = - 1 )
{
// Cancel this
e . Handled = true ;
}
else
{
2014-01-23 13:36:51 +00:00
//mxd. Check if * or / is pressed
2014-10-17 11:55:08 +00:00
if ( e . KeyChar = = '*' | | e . KeyChar = = '/' )
{
2014-01-23 13:36:51 +00:00
if ( this . SelectionStart - 1 > - 1 ) e . Handled = true ; //only valid when at the start of the text
}
2009-04-19 18:07:22 +00:00
// Check if + or - is pressed
2014-01-23 13:36:51 +00:00
else if ( ( e . KeyChar = = '+' ) | | ( e . KeyChar = = '-' ) )
2009-04-19 18:07:22 +00:00
{
2014-10-17 11:55:08 +00:00
string nonselectedtext ;
2009-04-19 18:07:22 +00:00
// Determine non-selected text
if ( this . SelectionLength > 0 )
{
nonselectedtext = this . Text . Substring ( 0 , this . SelectionStart ) +
this . Text . Substring ( this . SelectionStart + this . SelectionLength ) ;
}
else if ( this . SelectionLength < 0 )
{
nonselectedtext = this . Text . Substring ( 0 , this . SelectionStart + this . SelectionLength ) +
this . Text . Substring ( this . SelectionStart ) ;
}
else
{
nonselectedtext = this . Text ;
}
// Not at the start?
2014-10-17 11:55:08 +00:00
int selectionpos = this . SelectionStart - 1 ;
2009-04-19 18:07:22 +00:00
if ( this . SelectionLength < 0 ) selectionpos = ( this . SelectionStart + this . SelectionLength ) - 1 ;
if ( selectionpos > - 1 )
{
// Find any other characters before the insert position
2014-10-17 11:55:08 +00:00
string textpart = this . Text . Substring ( 0 , selectionpos + 1 ) ;
2009-04-19 18:07:22 +00:00
textpart = textpart . Replace ( "+" , "" ) ;
textpart = textpart . Replace ( "-" , "" ) ;
if ( textpart . Length > 0 )
{
// Cancel this
e . Handled = true ;
}
}
// Determine other prefix
2014-10-17 11:55:08 +00:00
char otherprefix = ( e . KeyChar = = '+' ? '-' : '+' ) ;
2009-04-19 18:07:22 +00:00
// Limit the number of + and - allowed
2014-10-17 11:55:08 +00:00
int numprefixes = nonselectedtext . Split ( e . KeyChar , otherprefix ) . Length ;
2009-04-19 18:07:22 +00:00
if ( numprefixes > 2 )
{
// Can't have more than 2 prefixes
e . Handled = true ;
}
else if ( numprefixes > 1 )
{
// Must have 2 the same prefixes
if ( this . Text . IndexOf ( e . KeyChar ) = = - 1 ) e . Handled = true ;
// Double prefix must be allowed
if ( ! allowrelative ) e . Handled = true ;
}
}
}
// Call base
base . OnKeyPress ( e ) ;
}
// Validate contents
protected override void OnValidating ( CancelEventArgs e )
{
2015-04-01 12:51:26 +00:00
//mxd. We may want "++" and "--" on their own...
if ( allowrelative & & ( this . Text = = "++" | | this . Text = = "--" ) )
{
// Call base and bail out
base . OnValidating ( e ) ;
return ;
}
2009-04-19 18:07:22 +00:00
// Strip prefixes
2014-10-17 11:55:08 +00:00
string textpart = this . Text . Replace ( "+" , "" ) . Replace ( "*" , "" ) . Replace ( "/" , "" ) ; //mxd
2009-04-19 18:07:22 +00:00
if ( ! allownegative ) textpart = textpart . Replace ( "-" , "" ) ;
// No numbers left?
if ( textpart . Length = = 0 )
{
// Make the textbox empty
this . Text = "" ;
2014-10-17 11:55:08 +00:00
}
else if ( allowdecimal ) //mxd
{
2013-06-10 14:04:23 +00:00
float value ;
2014-10-17 11:55:08 +00:00
if ( float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out value ) )
{
2014-01-23 13:36:51 +00:00
if ( value = = Math . Round ( value ) )
2015-03-23 14:19:23 +00:00
this . Text = this . Text . Replace ( textpart , value . ToString ( ) ) ;
2013-06-10 14:04:23 +00:00
}
2009-04-19 18:07:22 +00:00
}
// Call base
base . OnValidating ( e ) ;
}
2009-07-10 13:56:22 +00:00
// This checks if the number is relative
public bool CheckIsRelative ( )
{
2014-01-23 13:36:51 +00:00
// Prefixed with ++, --, * or /?
2014-09-15 08:15:22 +00:00
return ( ( this . Text . Length > 2 & & ( this . Text . StartsWith ( "++" ) | | this . Text . StartsWith ( "--" ) ) ) | |
( this . Text . Length > 1 & & ( this . Text . StartsWith ( "*" ) | | this . Text . StartsWith ( "/" ) ) ) ) ; //mxd
2009-07-10 13:56:22 +00:00
}
2009-04-19 18:07:22 +00:00
// This determines the result value
public int GetResult ( int original )
{
string textpart = this . Text ;
// Strip prefixes
2014-01-23 13:36:51 +00:00
textpart = textpart . Replace ( "+" , "" ) . Replace ( "-" , "" ) . Replace ( "*" , "" ) . Replace ( "/" , "" ) ; //mxd
2009-04-19 18:07:22 +00:00
// Any numbers left?
if ( textpart . Length > 0 )
{
2013-08-22 15:30:50 +00:00
int result ;
2009-04-19 18:07:22 +00:00
// Prefixed with ++?
if ( this . Text . StartsWith ( "++" ) )
{
// Add number to original
2013-08-22 15:30:50 +00:00
int . TryParse ( textpart , out result ) ;
2009-04-19 18:07:22 +00:00
return original + result ;
}
// Prefixed with --?
2013-08-22 15:30:50 +00:00
if ( this . Text . StartsWith ( "--" ) )
2009-04-19 18:07:22 +00:00
{
// Subtract number from original
2013-08-22 15:30:50 +00:00
int . TryParse ( textpart , out result ) ;
2009-04-19 18:07:22 +00:00
int newvalue = original - result ;
if ( ! allownegative & & ( newvalue < 0 ) ) newvalue = 0 ;
return newvalue ;
}
2014-01-23 13:36:51 +00:00
//mxd. Prefixed with *?
2014-10-17 11:55:08 +00:00
if ( this . Text . StartsWith ( "*" ) )
{
2014-01-23 13:36:51 +00:00
// Multiply original by number
float resultf ;
float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out resultf ) ;
int newvalue = ( int ) Math . Round ( original * resultf ) ;
if ( ! allownegative & & ( newvalue < 0 ) ) newvalue = 0 ;
return newvalue ;
}
//mxd. Prefixed with /?
2014-10-17 11:55:08 +00:00
if ( this . Text . StartsWith ( "/" ) )
{
2014-01-23 13:36:51 +00:00
// Divide original by number
float resultf ;
float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out resultf ) ;
if ( resultf = = 0 ) return original ;
int newvalue = ( int ) Math . Round ( original / resultf ) ;
if ( ! allownegative & & ( newvalue < 0 ) ) newvalue = 0 ;
return newvalue ;
}
2013-08-22 15:30:50 +00:00
//mxd. Return the new value
if ( ! int . TryParse ( this . Text , out result ) ) return original ;
if ( ! allownegative & & ( result < 0 ) ) return 0 ;
return result ;
2009-04-19 18:07:22 +00:00
}
2013-08-22 15:30:50 +00:00
// Nothing given, keep original value
return original ;
2009-04-19 18:07:22 +00:00
}
// This determines the result value
public float GetResultFloat ( float original )
{
// Strip prefixes
2014-10-17 11:55:08 +00:00
string textpart = this . Text . Replace ( "+" , "" ) . Replace ( "-" , "" ) . Replace ( "*" , "" ) . Replace ( "/" , "" ) ; //mxd;
2009-04-19 18:07:22 +00:00
// Any numbers left?
if ( textpart . Length > 0 )
{
2014-10-17 11:55:08 +00:00
float result ;
2009-04-19 18:07:22 +00:00
// Prefixed with ++?
if ( this . Text . StartsWith ( "++" ) )
{
// Add number to original
2013-06-04 13:59:24 +00:00
if ( ! float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out result ) ) result = 0 ;
2009-04-19 18:07:22 +00:00
return original + result ;
}
// Prefixed with --?
2014-01-23 13:36:51 +00:00
if ( this . Text . StartsWith ( "--" ) )
2009-04-19 18:07:22 +00:00
{
// Subtract number from original
2013-06-04 13:59:24 +00:00
if ( ! float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out result ) ) result = 0 ;
2009-04-19 18:07:22 +00:00
float newvalue = original - result ;
if ( ! allownegative & & ( newvalue < 0 ) ) newvalue = 0 ;
return newvalue ;
}
2014-01-23 13:36:51 +00:00
//mxd. Prefixed with *?
2014-10-17 11:55:08 +00:00
if ( this . Text . StartsWith ( "*" ) )
{
2014-01-23 13:36:51 +00:00
// Multiply original by number
if ( ! float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out result ) ) result = 0 ;
float newvalue = original * result ;
if ( ! allownegative & & ( newvalue < 0 ) ) newvalue = 0 ;
return newvalue ;
2009-04-19 18:07:22 +00:00
}
2014-01-23 13:36:51 +00:00
//mxd. Prefixed with /?
2014-10-17 11:55:08 +00:00
if ( this . Text . StartsWith ( "/" ) )
{
2014-01-23 13:36:51 +00:00
// Divide original by number
2015-03-23 14:19:23 +00:00
if ( ! float . TryParse ( textpart , NumberStyles . Float , CultureInfo . CurrentCulture , out result ) ) return original ;
2014-01-23 13:36:51 +00:00
float newvalue = ( float ) Math . Round ( original / result , 3 ) ;
if ( ! allownegative & & ( newvalue < 0 ) ) newvalue = 0 ;
return newvalue ;
}
//mxd. Return the new value
if ( ! float . TryParse ( this . Text , NumberStyles . Float , CultureInfo . CurrentCulture , out result ) ) return original ;
if ( ! allownegative & & ( result < 0 ) ) return 0 ;
return result ;
2009-04-19 18:07:22 +00:00
}
2014-01-23 13:36:51 +00:00
// Nothing given, keep original value
return original ;
2009-04-19 18:07:22 +00:00
}
2014-10-17 11:55:08 +00:00
//mxd
2015-03-23 14:19:23 +00:00
public void UpdateTextboxStyle ( )
{
UpdateTextboxStyle ( string . Empty ) ;
}
//mxd
public void UpdateTextboxStyle ( string tip )
2014-10-17 11:55:08 +00:00
{
this . ForeColor = ( allowrelative ? SystemColors . HotTrack : SystemColors . WindowText ) ;
if ( allowrelative )
{
2015-03-23 14:19:23 +00:00
tooltip . SetToolTip ( this , "Use ++ or -- prefixes to change\r\nexisting values by given value.\r\nUse * or / prefixes to multiply\r\nor divide existing values by given value." + Environment . NewLine + tip ) ;
}
else if ( ! string . IsNullOrEmpty ( tip ) )
{
tooltip . SetToolTip ( this , tip ) ;
2014-10-17 11:55:08 +00:00
}
else
{
tooltip . RemoveAll ( ) ;
}
}
2009-04-19 18:07:22 +00:00
#endregion
}
}