237 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C#
		
	
	
	
		
		
			
		
	
	
			237 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C#
		
	
	
	
|  | using Markdig; | |||
|  | using UnityEditor; | |||
|  | using UnityEngine; | |||
|  | using Markdig.Extensions.JiraLinks; | |||
|  | 
 | |||
|  | namespace WeChatWASM.MDV | |||
|  | { | |||
|  |     public class MarkdownViewer | |||
|  |     { | |||
|  |         private GUISkin         mSkin            = null; | |||
|  |         private string          mText            = string.Empty; | |||
|  |         private string          mCurrentPath     = string.Empty; | |||
|  |         private HandlerImages   mHandlerImages   = new HandlerImages(); | |||
|  |         private HandlerNavigate mHandlerNavigate = new HandlerNavigate(); | |||
|  | 
 | |||
|  |         private Vector2         mScrollPos       = Vector2.zero; | |||
|  |         private Layout          mLayout          = null; | |||
|  |         private bool            mRaw             = false; | |||
|  | 
 | |||
|  |         private static History  mHistory         = new History(); | |||
|  | 
 | |||
|  |         public MarkdownViewer( GUISkin skin, string path, string content ) | |||
|  |         { | |||
|  |             mSkin        = skin; | |||
|  |             mCurrentPath = path; | |||
|  |             mText        = content; | |||
|  | 
 | |||
|  |             mHistory.OnOpen( mCurrentPath ); | |||
|  |             mLayout = ParseDocument(); | |||
|  | 
 | |||
|  |             mHandlerImages.CurrentPath   = mCurrentPath; | |||
|  | 
 | |||
|  |             mHandlerNavigate.CurrentPath = mCurrentPath; | |||
|  |             mHandlerNavigate.History     = mHistory; | |||
|  |             mHandlerNavigate.FindBlock   = ( id ) => mLayout.Find( id ); | |||
|  |             mHandlerNavigate.ScrollTo    = ( pos ) => mScrollPos.y = pos; | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         public bool Update() | |||
|  |         { | |||
|  |             return mHandlerImages.Update(); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         Layout ParseDocument() | |||
|  |         { | |||
|  |             var context  = new Context( mSkin, mHandlerImages, mHandlerNavigate ); | |||
|  |             var builder  = new LayoutBuilder( context ); | |||
|  |             var renderer = new RendererMarkdown( builder ); | |||
|  | 
 | |||
|  |             var pipelineBuilder = new MarkdownPipelineBuilder() | |||
|  |                 .UseAutoLinks() | |||
|  |             ; | |||
|  | 
 | |||
|  |             if( !string.IsNullOrEmpty( Preferences.JIRA ) ) | |||
|  |             { | |||
|  |                 pipelineBuilder.UseJiraLinks( new JiraLinkOptions( Preferences.JIRA ) ); | |||
|  |             } | |||
|  | 
 | |||
|  |             var pipeline = pipelineBuilder.Build(); | |||
|  |             pipeline.Setup( renderer ); | |||
|  | 
 | |||
|  |             var doc = Markdown.Parse( mText, pipeline ); | |||
|  |             renderer.Render( doc ); | |||
|  | 
 | |||
|  |             return builder.GetLayout(); | |||
|  |         } | |||
|  | 
 | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  | #if !UNITY_2018 | |||
|  |         private float mHeight = 1.0f; | |||
|  | #endif | |||
|  | 
 | |||
|  |         protected Rect GetEditorRect() | |||
|  |         { | |||
|  | #if !UNITY_2018 | |||
|  | 
 | |||
|  |             // fix for Screen.height | |||
|  |             var offset = 450.0f; | |||
|  |             var scale  = 2.0f; | |||
|  | 
 | |||
|  |             // calculate working space | |||
|  |             if( Event.current.type == EventType.Layout ) | |||
|  |             { | |||
|  |                 mHeight = ( Screen.height - offset ) / scale; | |||
|  |             } | |||
|  | 
 | |||
|  |             // reserve space (we are going to paint on it directly) | |||
|  |             GUILayout.Space( mHeight ); | |||
|  | 
 | |||
|  |             // return working rect | |||
|  |             return new Rect( 0.0f, 10.0f, EditorGUIUtility.currentViewWidth, mHeight ); | |||
|  | #else | |||
|  |             GUILayout.FlexibleSpace(); | |||
|  |             var rectContainer = GUILayoutUtility.GetLastRect(); | |||
|  |             rectContainer.width = EditorGUIUtility.currentViewWidth; | |||
|  |             return rectContainer; | |||
|  | 
 | |||
|  | #endif | |||
|  |         } | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         public void Draw() | |||
|  |         { | |||
|  |             GUI.skin    = mSkin; | |||
|  |             GUI.enabled = true; | |||
|  | 
 | |||
|  |             // content rect | |||
|  | 
 | |||
|  |             var rectContainer = GetEditorRect(); | |||
|  | 
 | |||
|  | 
 | |||
|  |             // clear background | |||
|  | 
 | |||
|  |             var rectFullScreen = new Rect( 0.0f, rectContainer.yMin - 4.0f, Screen.width, Screen.height ); | |||
|  |             GUI.DrawTexture( rectFullScreen, GUI.skin.window.normal.background, ScaleMode.StretchToFill, false ); | |||
|  | 
 | |||
|  |             // scroll window | |||
|  | 
 | |||
|  |             var padLeft     = 8.0f; | |||
|  |             var padRight    = 4.0f; | |||
|  |             var padHoriz    = padLeft + padRight; | |||
|  |             var scrollWidth = GUI.skin.verticalScrollbar.fixedWidth; | |||
|  |             var minWidth    = rectContainer.width - scrollWidth - padHoriz; | |||
|  |             var maxHeight   = ContentHeight( minWidth ); | |||
|  | 
 | |||
|  |             var hasScrollbar =  maxHeight >= rectContainer.height; | |||
|  |             var contentWidth = hasScrollbar ? minWidth : rectContainer.width - padHoriz; | |||
|  |             var rectContent  = new Rect( -padLeft, 0.0f, contentWidth, maxHeight ); | |||
|  | 
 | |||
|  |             // draw content | |||
|  | 
 | |||
|  |             using( var scroll = new GUI.ScrollViewScope( rectContainer, mScrollPos, rectContent ) ) | |||
|  |             { | |||
|  |                 mScrollPos = scroll.scrollPosition; | |||
|  | 
 | |||
|  |                 if( mRaw ) | |||
|  |                 { | |||
|  |                     rectContent.width = minWidth - GUI.skin.button.fixedWidth; | |||
|  |                     DrawRaw( rectContent ); | |||
|  |                 } | |||
|  |                 else | |||
|  |                 { | |||
|  |                     DrawMarkdown( rectContent ); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             DrawToolbar( rectContainer, hasScrollbar ? scrollWidth + padRight : padRight ); | |||
|  |         } | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         float ContentHeight( float width ) | |||
|  |         { | |||
|  |             return mRaw ? GUI.skin.GetStyle( "raw" ).CalcHeight( new GUIContent( mText ), width ) : mLayout.Height; | |||
|  |         } | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         void DrawToolbar( Rect rect, float marginRight ) | |||
|  |         { | |||
|  |             var style  = GUI.skin.button; | |||
|  |             var size   = style.fixedHeight; | |||
|  |             var btn    = new Rect( rect.xMax - size - marginRight, rect.yMin, size, size ); | |||
|  | 
 | |||
|  |             if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( mRaw ? "btnRaw" : "btnFile" ) ) ) | |||
|  |             { | |||
|  |                 mRaw = !mRaw; | |||
|  |             } | |||
|  | 
 | |||
|  |             if( mRaw == false ) | |||
|  |             { | |||
|  |                 if( mHistory.CanForward ) | |||
|  |                 { | |||
|  |                     btn.x -= size; | |||
|  | 
 | |||
|  |                     if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( "btnForward" ) ) ) | |||
|  |                     { | |||
|  |                         Selection.activeObject = AssetDatabase.LoadAssetAtPath<TextAsset>( mHistory.Forward() ); | |||
|  |                     } | |||
|  |                 } | |||
|  | 
 | |||
|  |                 if( mHistory.CanBack ) | |||
|  |                 { | |||
|  |                     btn.x -= size; | |||
|  | 
 | |||
|  |                     if( GUI.Button( btn, string.Empty, GUI.skin.GetStyle( "btnBack" ) ) ) | |||
|  |                     { | |||
|  |                         Selection.activeObject = AssetDatabase.LoadAssetAtPath<TextAsset>( mHistory.Back() ); | |||
|  |                     } | |||
|  |                 } | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         void DrawRaw( Rect rect ) | |||
|  |         { | |||
|  |             EditorGUI.SelectableLabel( rect, mText, GUI.skin.GetStyle( "raw" ) ); | |||
|  |         } | |||
|  | 
 | |||
|  |         //------------------------------------------------------------------------------ | |||
|  | 
 | |||
|  |         void DrawMarkdown( Rect rect ) | |||
|  |         { | |||
|  |             switch( Event.current.type ) | |||
|  |             { | |||
|  |                 case EventType.Ignore: | |||
|  |                     break; | |||
|  | 
 | |||
|  |                 case EventType.ContextClick: | |||
|  |                     var menu = new GenericMenu(); | |||
|  |                     menu.AddItem( new GUIContent( "View Source" ), false, () => mRaw = !mRaw ); | |||
|  |                     menu.ShowAsContext(); | |||
|  | 
 | |||
|  |                     break; | |||
|  | 
 | |||
|  |                 case EventType.Layout: | |||
|  |                     mLayout.Arrange( rect.width ); | |||
|  |                     break; | |||
|  | 
 | |||
|  |                 default: | |||
|  |                     mLayout.Draw(); | |||
|  |                     break; | |||
|  |             } | |||
|  |         } | |||
|  |     } | |||
|  | } |